2012-04-14 140 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