- 問題
- N-act構成にしたとき、ネットワークが切れてまたつながった場合にデータ不整合が起きるか。復旧の方法はあるか。
- 結論
- 起きる。簡単な復旧方法はなさげ。
- Mnesiaレプリカのあるノードが一時的に通信不能になり、その間にMnesiaオリジナル*1が不整合の起きるレコード更新を行うと、Mnesiaレプリカが復帰できない。
- set_master_nodes/2は微妙(ざっとリファレンスを見た限りでは、不整合を解決する方法はこれくらいしかなさげ)
- 使ったマシン
まずは準備。
dom0側
[kuenishi@] $ erl -name a@192.168.0.72 -setcookie hoge Erlang (BEAM) emulator version 5.6.3 [source] [64-bit] [smp:4] [async-threads:0] [kernel-poll:false] Eshell V5.6.3 (abort with ^G) (a@192.168.0.72)1> mnesia:start(). ok
domU側
kuenishi@domU1debian:~$ erl -name a@192.168.0.31 -setcookie hoge Erlang (BEAM) emulator version 5.6.3 [source] [64-bit] [async-threads:0] [kernel -poll:false] Eshell V5.6.3 (abort with ^G) (a@192.168.0.31)1> net_adm:ping('a@192.168.0.72'). pong (a@192.168.0.31)2> mnesia:create_schema([node(), 'a@192.168.0.72']). ok (a@192.168.0.31)3> rd( user, {id, age}). user (a@192.168.0.31)5> mnesia:start(). ok (a@192.168.0.31)6> mnesia:create_table( user, [ (a@192.168.0.31)6> {ram_copies, [node(), 'a@192.168.0.72']}, (a@192.168.0.31)6> {attributes, record_info( fields, user )} (a@192.168.0.31)6> ]). {atomic,ok}
これでmnesiaが準備できたので、両方のノードでひとつずつレコード作成。
(a@192.168.0.31)7> mnesia:transaction(fun()-> mnesia:write(#user{id=1,age=1}) en d). {atomic,ok} (a@192.168.0.31)8> mnesia:dirty_read(user,1). [#user{id = 1,age = 1}]
dom0
(a@192.168.0.72)5> rd(user, {id,age}). user (a@192.168.0.72)6> mnesia:transaction(fun()->mnesia:write(#user{id=2,age=2}) end). {atomic,ok} (a@192.168.0.72)7> mnesia:dirty_read(user,2). [#user{id = 2,age = 2}] (a@192.168.0.72)9> mnesia:dirty_read(user,1). [#user{id = 1,age = 1}]
これでどっちも見えている。ここで、両者を接続するネットワークを切断(domU側のeth0を止めた)。
結果は書かないけど、この時点でのdirty_readはどっちもできていた。
ネットワークが切断された状態で更新をかける。
domU
(a@192.168.0.31)12> mnesia:transaction(fun()-> mnesia:write(#user{id=1,age=231}) end). =ERROR REPORT==== 22-Nov-2008::12:11:03 === ** Node 'a@192.168.0.72' not responding ** ** Removing (timedout) connection ** {atomic,ok}
タイムアウト?まで少し時間かかるけど、コミットできちゃう。dom0でも同様にコミットできてしまった。ここでネットワークが切れたことを検出しているみたい。
で、ここでもっかいifup eth0してネットワークをつなぐ。ネットワークが繋がっても、明示的にbeam同士を接続しないといけないらしい。
dom0側で
(a@192.168.0.72)18> mnesia:change_config(extra_db_nodes, ['a@192.168.0.31']). =ERROR REPORT==== 22-Nov-2008::12:23:42 === Mnesia('a@192.168.0.72'): ** ERROR ** mnesia_event got {inconsistent_database, running_partitioned_network, 'a@192.168.0.31'} =ERROR REPORT==== 22-Nov-2008::12:23:42 === Mnesia('a@192.168.0.72'): ** ERROR ** mnesia_event got {inconsistent_database, starting_partitioned_network, 'a@192.168.0.31'} {ok,['a@192.168.0.31']} (a@192.168.0.72)19>
げげっ。domU側でも何かでてる。
(a@192.168.0.31)21> =ERROR REPORT==== 22-Nov-2008::12:23:42 === Mnesia('a@192.168.0.31'): ** ERROR ** mnesia_event got {inconsistent_database, running_partitioned_network, 'a@192.168.0.72'} (a@192.168.0.31)21>
というわけで、問題がいくつか。
- ネットワークが切れて、不整合を起こすコミットが成功して、ネットワークがまた繋がった場合に、不整合を解決する方法
- ネットワークが切れて接続できないノードに対しても更新要求を送るので、タイムアウトまで待ってしまい、結果的に(多分)qpsが下がる
(追記)
mem_copiesだろうとdisc_copiesだろうと、不整合が起きたままの状態で同じテーブルを参照することはできるらしい。レコードを上書きすれば不整合はなくなる。
- 参考
- Erlang: Mnesiaで分散DB
- record_infoの引数がちょと古いけど、わかりやすい入門。
- Mnesia のレプリケーションを試す
- コメント欄より
- Erlang: Mnesiaで分散DB
ram_copies <-> ram_copies と disc_copies <-> ram_copies は2つ目を後から起動しても上手くいくのですが disc_copies <-> disc_copies のレプリケーションは一度 mnesia を stop させないとダメっぽい
-
-
- な、なんだってー(ry
-
*1:という言い方が合ってるかどうかは別にして