经过一些实验,我发现了以下内容:
- 如果两个节点之间存在节点断开连接和重新连接而没有重新启动 mnesia,则 Mnesia 认为网络是分区的。
- 即使在断开连接期间没有发生 Mnesia 读/写操作也是如此。
- 必须重新启动 Mnesia 本身才能清除分区网络事件 - 在网络分区后您不能这样
force_load_table
做。
- 只有 Mnesia 需要重新启动才能清除网络分区事件。您不需要重新启动整个节点。
- Mnesia 通过让新重新启动的 Mnesia 节点用来自另一个 Mnesia 节点的数据(启动表加载算法)覆盖其表数据来解决网络分区问题。
- 通常,节点会从运行时间最长的节点复制表(这是我看到的行为,我还没有验证这是明确编码的,而不是其他东西的副作用)。如果你从集群中断开一个节点,在两个分区(断开的节点和它的旧对等节点)中进行写入,关闭所有节点并重新启动它们,首先启动断开的节点,断开的节点将被认为是主节点和它的数据将覆盖所有其他节点。没有表比较/校验和/仲裁行为。
mnesia:stop(), mnesia:start()
因此,为了回答我的问题,可以通过在您决定丢弃其数据的分区(我将其称为丢失分区)中的节点上执行来执行半在线恢复。执行mnesia:start()
调用将导致节点联系分区另一侧的节点。如果丢失分区中有多个节点,您可能希望将主节点设置为将表加载到获胜分区中的节点 - 否则我认为它有可能从丢失分区中的另一个节点加载表,因此返回分区网络状态。
不幸的是,mnesia 不支持在启动表加载阶段合并/协调表内容,也不支持在启动后返回表加载阶段。
合并阶段尤其适用于 ejabberd,因为节点仍将具有用户连接,因此知道它拥有/应该是最新的用户记录(假设每个集群有一个用户连接)。如果存在合并阶段,节点可以过滤用户数据表,保存连接用户的所有记录,照常加载表,然后将保存的记录写回 mnesia 集群。