Mnesia に保存されたデータを永続化する(後からノードを追加しても大丈夫)
id:cooldaemon:20070919 で書いた Mnesia のレプリケーションの記事で、id:Hamano 氏からコメントで
便利ですよねー、mnesia のレプリケーション。
でも最近悩んでいるのが ram_copies <-> ram_copies と disc_copies <-> ram_copies は2つ目を後から起動しても上手くいくのですが disc_copies <-> disc_copies のレプリケーションは一度 mnesia を stop させないとダメっぽいんですよね。
続編に期待しています^^;
とリクエストを頂いたので、disc_copies <-> disc_copies を無停止でやってみました。
まずは、テストで書いたコードを載せます。
-module(mnesia_test). -record(store, {key, value}). -export([start/0, start/1, restart/1]). start() -> mnesia:create_schema([node()]), mnesia:start(), mnesia:create_table(store, [ {disc_copies, [node()]}, {attributes, record_info(fields, store)} ]). start(Nodes) -> mnesia:start(), mnesia:change_config(extra_db_nodes, Nodes), mnesia:change_table_copy_type(schema, node(), disc_copies), mnesia:add_table_copy(store, node(), disc_copies). restart() -> mnesia:start().
いろいろ省いてますが、一応、コンパイルしてすぐ試せるコードになってます。
次に ram_copies 版との違いを挙げます
- 複製元となるノードでは mnesia:start/0 より先に mnesia:create_schema/1 を実行する
- 複製先となるノードでは mnesia:change_table_copy_type/3 で schema テーブルをディスクに保存する
- 複製元も複製先も再起動時には、mnesia:start/0 を実行するだけで OK!!
mnesia:info/0 で見ると、schema もただのテーブルなので、もしやと思って試してみたらビンゴでした(w;
最後に確認を・・・
(hostname -s の実行結果は imac と仮定)
% erl -sname a (a@imac)1> mnesia_test:start(). {atomic,ok}
% erl -sname b (b@imac)1> net_adm:ping(a@imac). pong (b@imac)2> mnesia_test:start(nodes()). {atomic,ok} (b@imac)3> mnesia:info(). ---> Processes holding locks <--- ---> Processes waiting for locks <--- ---> Participant transactions <--- ---> Coordinator transactions <--- ---> Uncertain transactions <--- ---> Active tables <--- store : with 0 records occupying 279 words of mem schema : with 2 records occupying 519 words of mem ===> System info in version "X.X.X", debug level = none <=== opt_disc. Directory "/path/to/Mnesia.b@imac" is used. use fallback at restart = false running db nodes = [a@imac,b@imac] stopped db nodes = [] master node tables = [] remote = [] ram_copies = [] disc_copies = [schema,store] disc_only_copies = [] [{a@imac,disc_copies},{b@imac,disc_copies}] = [schema,store] 6 transactions committed, 0 aborted, 0 restarted, 2 logged to disc 0 held locks, 0 in queue; 0 local transactions, 0 remote 0 transactions waits for other nodes: [] ok (b@imac)4>halt().
% erl -sname b (b@imac)1> net_adm:ping(a@imac). pong (b@imac)2> mnesia_test:restart(). ok (b@imac)3> mnesia:info(). ---> Processes holding locks <--- ---> Processes waiting for locks <--- ---> Participant transactions <--- ---> Coordinator transactions <--- ---> Uncertain transactions <--- ---> Active tables <--- store : with 0 records occupying 279 words of mem schema : with 2 records occupying 519 words of mem ===> System info in version "X.X.X", debug level = none <=== opt_disc. Directory "/path/to/Mnesia.b@imac" is used. use fallback at restart = false running db nodes = [a@imac,b@imac] stopped db nodes = [] master node tables = [] remote = [] ram_copies = [] disc_copies = [schema,store] disc_only_copies = [] [{a@imac,disc_copies},{b@imac,disc_copies}] = [schema,store] 4 transactions committed, 0 aborted, 0 restarted, 0 logged to disc 0 held locks, 0 in queue; 0 local transactions, 0 remote 0 transactions waits for other nodes: [] ok