什么是备份的正确方法/恢复一个Mnesia数据库?(what is the proper way t

2019-07-28 23:45发布

警告:背景信息是相当长的。 跳到底部,如果你认为你需要之前的背景信息的问题。 升值的时候,这是要带!

我一直都在网上(读谷歌),我还没有找到一个很好的答案。 是的,有很多的链接和参考对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(mydatabase@host, mnesia, backup, ["/tmp/backup.bup"]).
> rpc:call(mydatabase@host, mnesia, restore, ["/tmp/backup.bup", [{default_op, recreate_tables}]]).

当然,这是很简单。 现在,这里是棘手的事情....

  • 比方说,你正在服用每日备份。 而你的Mnesia数据库服务器死了,你是被迫更换硬件。 如果你想恢复DB原样,那么你需要命名与它以前有相同名称的新硬件,你也需要命名的节点相同。
  • 如果你想改变硬件和/或节点(的名称)...或者你想在不同的机器上恢复,那么你就需要去通过node_change过程。 (描述在这里和在Mnesia的文档)

但这里情况变得有些复杂。 而我的熟人,谁是Erlang和Mnesia的专家建议,Mnesia的复制是严重错误的,你不应该使用它(目前有没有办法,我知道的,什么是你要实现更好的版本的机会;不可能)

所以,你有两个节点()被复制RAM和盘基表。 你一直保持使用默认BackupMod与标准备份定期备份数据库的政策。 有一天,经理要求您验证备份。 只有当你试图恢复你的数据库:

{atomic,[]}

并根据文件,这意味着没有错误...,但没有表被恢复。

不想跑你记住,节点()和主机名必须匹配,以便您更改主机名和-sname参数去那里数据被备份的计算机匹配change_node程序。 而这一次你会得到一个奇怪的错误:

{aborted,{'EXIT',{aborted,{bad_commit,{missing_lock,mydatabase@otherhost}}}}}

还没想运行change_node过程我很快恢复克隆我的服务器,这样我有两个类似的机器。 我的名字,然后适当地匹配生产服务器。 我开始恢复过程。 找到了! 我现在恢复服务器上的实际工作数据。

我想说,这是路的尽头......但我还没有问一个问题还没有和这么点....所以在这里它是什么?

问:如果我要恢复这是从复制的Mnesia节点的集群拍摄,我怎么修改文件(类似于change_node程序),从而使其它节点忽略或从备份删除备份?

问略有不同:如何还原复制的多节点()Mnesia的数据库中的单个节点上()?

Answer 1:

我认为这个问题属于在所涉及到一个简单的Mnesia的问题更广泛的类别:

如何重新命名一个Mnesia节点?

第一,简单的解决方案,如果你的数据库不是很大,就是用函数mnesia:traverse_backup功能(见Mnesia的用户指南 )。 以下是从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的数据库来检查备份项的格式,如果你想成为肯定。

希望这可以帮助!



Answer 2:

我有一个非常很难得到这个工作,所以我将分享我所经历的步骤。

通过备份中要恢复(单个节点)分布式系统中的节点开始:

> mnesia:backup("/path/to/backup").

请确保以下适应change_node_name可你要还原到的节点上:

-module(move_backup).
-export([set_node_name/4]).                                                                                                    

set_node_name(From, To, Source, Target) ->
    Switch =
        fun (Nodes) ->
                case lists:member(From, Nodes) of
                    true -> [To];
                    false -> []
                end
        end,
    Convert =
        fun({schema, db_nodes, Nodes}, Acc) ->
                {[{schema, db_nodes, 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, Switch(Val)};
                                false-> {Key, Val}
                            end
                    end,
                {[{schema, Tab, lists:map(OptSwitch, CreateList)}], Acc};
           (Other, Acc) ->
                {[Other], Acc}
        end,
    mnesia:traverse_backup(Source, Target, Convert, switched).

转换备份:

> move_backup:set_node_name('before@host', 'after@host', "/path/to/backup", "/path_to_backup_converted").

我要去假设新节点完全是空的(如果不是这种情况下,你可能想改变default_op参数)。 有两种选择,一个是现场还原:

> mnesia:restore("/path/to/backup_converted", [{default_op, recreate_tables}]).

这是伟大的,但如果你有一个大的数据库可能会使用大量内存(我的是10GB〜所以这导致了内存溢出异常)。 另一种方法是安装一个备用,并重新启动你的shell:

> mnesia:install_fallback("/path/to/backup_converted").
> q().

然后当你重新启动外壳程序(假设你使用正确的节点名),它会导入完整的数据库。



文章来源: what is the proper way to backup/restore a mnesia database?