2012-04-14 121 views
11

警告:背景信息相當長。如果您認爲在背景信息之前需要該問題,請跳至底部。欣賞這將要花費的時間!什麼是備份/恢復mnesia數據庫的正確方法?

我一直在網絡上(讀谷歌),我還沒有找到一個很好的答案。是的,在erlang.org網站上有很多鏈接和對Mnesia文檔的參考,但即使這些鏈接也受版本限制。

因此,在最簡單的情況下,您當前連接到的節點()與表集的所有者相同,則備份/恢復將工作。例如:

$ erl -sname mydatabase 

> mnesia:start(). 
> mnesia:create_schema(...). 
> mnesia:create_table(...). 
> mnesia:backup("/tmp/backup.bup"). 
> mnesia:restore("/tmp/backup.bup", [{default_op, recreate_tables}]). 

嘿,這個作品很棒!

但是,如果數據庫實際上是一個遠程節點()或遠程節點()上的遠程對接上運行,那麼你必須啓動備份這樣:

$ erl -sname mydbadmin 

> rpc:call([email protected], mnesia, backup, ["/tmp/backup.bup"]). 
> rpc:call([email protected], mnesia, restore, ["/tmp/backup.bup", [{default_op, recreate_tables}]]). 

當然,這很簡單太。現在,這裏是棘手的事情......

  • 假設你正在採取每日備份。而你mnesia數據庫服務器死亡,你不得不更換硬件。如果您想按原樣還原數據庫,則需要使用與之前相同的名稱命名NEW硬件,並且還需要命名相同的節點。
  • 如果要更改硬件和/或節點的名稱()...或者要在其他計算機上恢復,則需要執行node_change過程。 (描述here和mnesia文檔)

但是,這裏是事情變得複雜的地方。雖然我的熟人,erlang和mnesia的專家建議mnesia的複製是嚴重的缺陷,並且你不應該使用它(目前我沒有選擇,我知道你有什麼機會實現更好的版本;不是可能)

因此,您有兩個節點()複製基於RAM和光盤的表。您一直在使用默認的BackupMod維護一個使用標準備份定期備份數據庫的策略。有一天,一位經理要求您驗證備份。只有當你試圖恢復數據庫您可以:

{atomic,[]} 

而且根據文檔,這意味着沒有錯誤...,但沒有表被恢復。

不想運行change_node過程,您應該記住node()和hostname必須匹配,以便更改主機名和-sname參數以匹配備份數據的計算機。而這一次你會得到一個奇怪的錯誤:

{aborted,{'EXIT',{aborted,{bad_commit,{missing_lock,[email protected]}}}}} 

還沒想運行change_node過程我很快恢復克隆我的服務器,這樣我有兩個類似的機器。然後我適當地命名以匹配生產服務器。我開始恢復過程。找到了!我現在在恢復服務器上有真實的工作數據。

我想說,這是路的盡頭......但我還沒有問過一個問題,所以......這麼說呢?

問題:如果我要恢復這是從複製的Mnesia節點的集羣進行的備份,我怎麼修改文件(類似於change_node程序),從而使其它節點要麼被忽略或刪除備份?

問略有不同:如何還原複製的多節點()Mnesia的數據庫中的單個節點上()?

+0

也應該看到http://stackoverflow.com/questions/463400/how-to-rename-the-node-running-a-mnesia-database。 – 2013-10-09 17:32:31

回答

7

我認爲這個問題屬於在Mnesia的問題更廣泛的類別,都涉及到一個簡單的:

How do I rename a Mnesia node?

第一和最簡單的解決辦法,如果你的數據庫不是很大,就是用的Mnesia :traverse_backup函數(請參閱Mnesia User guide)。 以下是從Mnesia的用戶指南的例子:

change_node_name(Mod, From, To, Source, Target) -> 
    Switch = 
     fun(Node) when Node == From -> To; 
      (Node) when Node == To -> throw({error, already_exists}); 
      (Node) -> Node 
     end, 
    Convert = 
     fun({schema, db_nodes, Nodes}, Acc) -> 
       {[{schema, db_nodes, lists:map(Switch,Nodes)}], Acc}; 
      ({schema, version, Version}, Acc) -> 
       {[{schema, version, Version}], Acc}; 
      ({schema, cookie, Cookie}, Acc) -> 
       {[{schema, cookie, Cookie}], Acc}; 
      ({schema, Tab, CreateList}, Acc) -> 
       Keys = [ram_copies, disc_copies, disc_only_copies], 
       OptSwitch = 
        fun({Key, Val}) -> 
          case lists:member(Key, Keys) of 
           true -> {Key, lists:map(Switch, Val)}; 
           false-> {Key, Val} 
          end 
        end, 
       {[{schema, Tab, lists:map(OptSwitch, CreateList)}], Acc}; 
      (Other, Acc) -> 
       {[Other], Acc} 
     end, 
    mnesia:traverse_backup(Source, Mod, Target, Mod, Convert, switched). 

view(Source, Mod) -> 
    View = fun(Item, Acc) -> 
        io:format("~p.~n",[Item]), 
        {[Item], Acc + 1} 
      end, 
    mnesia:traverse_backup(Source, Mod, dummy, read_only, View, 0). 

這裏最重要的部分是{schema, db_nodes, Nodes}元組這讓你重新命名或更換數據庫節點的操作。

順便說一句,我使用的功能在過去,有一兩件事我注意到的是Mnesia的版本之間的備份格式條款的變化,但也許它就是被我寫不好的代碼。只要打印一個小型mnesia數據庫的備份日誌來檢查備份術語格式,如果你想確定。

希望這會有所幫助!

+0

我有文本,它沒有說任何關於支持或恢復mnesia服務器集羣的任何信息。 – Richard 2012-04-22 16:46:31

+0

您在您的問題中提到您瞭解更改節點示例,該示例也包含在我指出的文檔中。如果我正確理解你的問題,在同一個例子中你可以看到元組{schema,db_nodes,Nodes}被檢查:這個元組包含爲Mnesia數據庫註冊的節點。 – 2012-04-23 00:06:06

+0

啊!我錯過了change_node代碼。 (你的回答並沒有提到這個問題,但是,change_node()應該是正確的答案。)謝謝。 – Richard 2012-04-24 19:43:25