从mnesia群集中删除运行节点

时间:2014-07-19 22:23:25

标签: erlang mnesia

我需要从mnesia群集中删除正在运行的节点。这是一个需要执行某些维护的合法节点。但是,我们希望保持此节点运行并为请求提供服务。我找到了this帖子。这有助于将其从其他节点中删除。但是,一旦在孤立节点上重新启动mnesia,它就会返回到集群中的其他节点。

从每个非孤立节点,我运行一个执行以下操作的脚本:

    rpc:call('node_to_be_orphaned', mnesia, stop, []),
    mnesia:del_table_copy(schema, 'node_to_be_orphaned'),

^^此时,mnesia:system_info(db_nodes)显示该节点确实已被删除。

    rpc:call('node_to_be_orphaned', mnesia, start, []),

现在回来了。啊!

所以,然后我尝试翻转它并从孤儿中删除其他节点,先添加以下内容。

    rpc:call(ThisNode, mnesia, stop, []),
    rpc:call('node_to_be_orphaned', mnesia, del_table_copy, [schema, node()]),
    rpc:call(ThisNode, mnesia, start, []),

这只会创建一个没有区别的循环。

有没有办法让节点退出mnesia群集,同时让它保持正常运行?

非常感谢任何和所有指导

1 个答案:

答案 0 :(得分:1)

架构正在困扰着你。您可以添加节点,但在保留表副本的同时删除它们是错误的。除了接收新模式之外,当节点连接到分布式模式时会发生这种情况:

  

将节点添加到复制架构的节点列表中   影响两件事。首先,它允许将其他表复制到   这个节点。其次会导致Mnesia尝试联系节点   启动光盘完整节点

这是the documentation关于在保持架构在节点上运行的同时从分布式表中断开节点的说法:

  

函数调用mnesia:del_table_copy(schema,mynode @ host)删除   来自Mnesia系统的节点'mynode @ host'。如果调用失败   mnesia正在'mynode @ host'上运行。其他的mnesia节点永远不会   尝试再次连接到该节点。请注意,如果有光盘驻留   节点'mynode @ host'上的模式,整个mnesia目录应该   被删除。这可以使用mnesia:delete_schema / 1来完成。 如果是mnesia   再次在节点'mynode @ host'上启动,目录没有   被清除后,mnesia的行为未定义

现有的分布式架构无法保留在断开连接的节点上。您必须重新创建一个,并复制表信息。

如果您希望在节点上保留当前架构,可以从中删除任何共享表,而是使用纯本地表。

如果您真的希望从架构中删除该节点,您可以导出数据,删除架构并创建一个新的未分配的架构,并导入数据,以进行测试和开发。


以下是您可以在两种情况下使用的一些有用功能:

复制mnesia表

Mnesia表格可以轻松复制,就像在这个例子中我只是为了它的纯粹乐趣而编写(并测试过):

copy_table(FromTable,ToTable) ->
    mnesia:create_table(ToTable, [
                        {attributes, mnesia:table_info(FromTable,attributes)},
                        {index, mnesia:table_info(FromTable,index)},
                        % Add other attributes to be inherited, if present
                        {record_name,FromTable},
                        {access_mode, read_write},
                        {disc_copies,[node()]}
                        ]),

    Keys = mnesia:dirty_all_keys(FromTable),
    CopyJob = fun(Record,Counter) ->
            mnesia:write(ToTable,Record,write),
            Counter + 1
            end,

    mnesia:transaction(fun() -> mnesia:foldl(CopyJob,0,FromTable) end).

此函数会将任何表(分布式或非分布式)复制到仅仅本地的表,保留其属性和记录定义。你必须使用mnesia:read


将mnesia表格导出/导入文件

此其他函数将mnesia表导出到文件,然后再将其导入。他们需要一些小的调整才能将它们导入任意命名表。 (你可以使用mnesia:ets / 1来获得纯粹的体验):

export_table(Table) ->
    Temp = ets:new(ignoreme,[bag,public]),
    Job  = fun(Key) ->
        [Record] = mnesia:dirty_read(Table,Key),
        ets:insert(Temp,Record) end,
    Keys = mnesia:dirty_all_keys(Table),
    [Job(Key) || Key <- Keys],
    Path = lists:concat(["./",atom_to_list(Table),".ets"]),
    ets:tab2file(Temp,Path,[{extended_info,[md5sum,object_count]}]),
    ets:delete(Temp).





import_table(Table) ->
    Path = lists:concat(["./",atom_to_list(Table),".ets"]),
    {ok,Temp} = ets:file2tab(Path,[{verify,true}]),
    {atomic,Count} = mnesia:transaction(fun() ->
        ets:foldl(fun(Record,I) -> mnesia:write(Record),I+1 end
             ,0
             ,Temp)
        end),
    ets:delete(Temp).