Col*_*tor 6 mysql auto-increment database-replication mariadb master-master
我们使用主-主复制来避免写入副本会使其与真正的主服务器不同步以及我们希望切换主服务器的情况。然而,自动增量字段有一个看似已知的问题,它会导致“键‘主’的重复条目”,到目前为止我还没有找到好的解决方案,所以提出这个问题。
情况:两个主服务器都将 INSERT 语句插入到具有 AUTOINCREMENT 字段的表中。当它们同时 INSERT 时(是的,发生了......)并且因此具有相同的编号,它们最终都无法从另一个主服务器启动该语句并使复制过程停止。
似乎这个问题很常见,只是我发现的当前解决方案似乎不够。
首先,假设特定行并不重要,这是发生这种情况时在两台服务器上启动的补救措施
STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; START SLAVE; SELECT sleep(0.5); SHOW SLAVE STATUS\G\
Run Code Online (Sandbox Code Playgroud)
这可以根据需要多次启动,以确保所有这些错误都得到解决。
https://mariadb.com/kb/en/auto_increment/#replication的另一个建议解决方案是
为了使 master-master 或 Galera 安全地使用 AUTO_INCRMENT,应该使用系统变量 auto_increment_increment 和 auto_increment_offset 为每个服务器生成唯一的值。
问题是此设置虽然在所有表中创建“洞”,但不使用顺序 ID。
对于这种情况是否有更好的解决方案,例如“重复执行某事”?
查看https://mariadb.com/kb/en/binary-log-formats/我也很好奇为什么 MIXED 模式不认为这些 INSERT 语句不安全,尽管它们显然是……
要回答您的问题,您不能使用INSERT ON DUPLICATE...,因为复制至少会延迟提交和写入二进制日志所需的时间。如果两个实例都是可写的,那么您总是可以获得“裂脑”效果。
我在不使用自动增量增量的情况下解决此问题的方法是使一个实例可写,另一个实例只读。如果您需要切换主实例,请将两个实例短暂设置为只读,让复制完全进行,以便它们同步,然后将第二个实例设置为读写。
更新以回应您在上述问题中添加的另一点:
没有任何模式或二进制日志格式(例如 MIXED)可以检测事务何时在另一个实例上执行 INSERT。实例了解其源上运行的内容的唯一方法是读取 binlog 事件,但另一个实例在提交其事务之前不会写入 binlog。
确保分布式系统中不发生冲突的唯一方法是使用某种全局锁定,允许一个实例或另一个实例启动事务。但这不是 MySQL 复制的工作原理。