master-master如何同时进行活动的mysql复制处理唯一键值。 对于主键值,我们可以设置auto_increment_increment和auro_increment_offset参数以避免主键auto_increment冲突。 但是类似地,如何在这里处理唯一的键约束呢?
答案 0 :(得分:0)
答案很简单:不处理它们。
由于复制是异步的,因此如果同时写入主-主复制集群的两个节点,则有可能导致split-brain errors。也就是说,您可以在两个复制节点上成功插入,但是当复制副本重播另一个复制副本的时间时,则会导致冲突,因为复制副本已经插入了具有冲突值的行。
外键约束可能会发生类似的问题。例如,您可以插入带有FK的行,该行引用另一个表中的父行,即使同时有人在其他节点中删除了该父行也是如此。复制两个更改后,将导致错误。
如果在触发器中实现了更复杂的约束,则可以创建相同的效果。例如,假设您编写了一个触发器,仅当表中至少剩余5行时才允许您从表中删除行。您删除一行,触发器将允许它。但是随后该节点从另一个节点复制了一个删除,导致表中仅剩下4个节点的无效状态。
以下有几种防止脑裂错误的方法:
仅允许在一个节点上进行写入,至少对于具有UNIQUE KEY或FOREIGN KEY或具有其他可能会导致脑裂的约束的给定表而言。这是最常见的解决方案,通常使其中一个节点成为全局只读的(不仅对于一个表,而且对于整个实例)。
使用某种全局信号量“锁定”对给定表的访问。信号量命名哪个节点允许写入表,并且连接到副本集的所有应用程序都必须遵守该信号量。您可以更改信号量,但是只有在一个节点上进行的所有更改都已复制到另一节点之前,才能进行更改。但这违背了允许在多个节点上同时写入的目标。
强制执行同步复制。也就是说,在有复制更改挂起时,您无法对节点进行任何更改。 Galera Cluster具有一种模式,其中节点上的本地更改(甚至是SELECT语句)必须等待,直到播放了所有未决的二进制日志为止。
使所有写入异步但有序。与其直接写入数据库,不如写入一个消息队列,然后让一个后端处理器以串行顺序使用该队列,并应用更改。这仍然可能导致错误,例如不允许将DELETE减少到少于5行的示例。但是至少这不会是裂脑错误。