我们使用主-主复制来避免这样的情况,即写入副本会使其与真正的主副本失去同步,并且我们希望切换主副本。然而,AUTOINCREMENT字段有一个似乎已知的问题,它会导致“重复输入'PRIMARY'键”,到目前为止我还没有找到很好的解决方案,所以问这个问题。
形势:两个主服务器都将INSERT语句插入到具有AUTOINCREMENT字段的表中。当两个主服务器同时(是的,发生......)插入此语句并使用相同的编号时,两个主服务器都将无法从另一个主服务器启动语句,并停止复制过程。
似乎这个问题很普遍,只是我找到的目前的解决方案似乎不够。
首先,假设特定的行不重要,下面是发生这种情况时在两台服务器上启动的补救措施
STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; START SLAVE; SELECT sleep(0.5); SHOW SLAVE STATUS\G\
可以根据需要多次启动此操作,以确保所有这些错误都向前移动。
www.example.com提供的另一个建议解决方案https://mariadb.com/kb/en/auto_increment/#replication是
要使master-master或Galera安全地使用AUTO_INCREMENT,应使用系统变量auto_increment_increment和auto_increment_offset为每个服务器生成唯一的值。
问题是,此设置在所有表中创建“孔”时,不使用顺序ID。
对于这种情况,是否有更好的解决方案,如ON DUPLICATE?
在研究https://mariadb.com/kb/en/binary-log-formats/时,我也很好奇为什么MIXED模式不认为这些INSERT语句是不安全的,尽管它们显然是不安全的。
1条答案
按热度按时间i2byvkas1#
为了回答您的问题,您不能使用
INSERT ON DUPLICATE...
,因为复制至少会延迟提交和写入二进制日志所需的时间。如果两个示例都是可写的,您总是会得到“裂脑”效果。我解决这个问题的方法是不使用自动增量增量,而是将一个示例设置为可写,而另一个示例设置为只读。如果需要切换哪个是主示例,请将两个示例都设置为只读,让复制完全通过,以便它们保持同步,然后将第二个示例设置为读写。
更新以回应您在上述问题中添加的另一点:
没有任何模式或binlog格式(例如MIXED)可以检测到事务处理何时在其他示例上执行INSERT。示例知道其源上运行了什么的唯一方式是它读取binlog事件,但其他示例在提交其事务处理之前不会写入binlog。
确保分布式系统中没有冲突的唯一方法是使用某种全局锁定,允许一个示例或另一个示例启动事务,但MySQL复制不是这样工作的。