双主MySQL自增冲突必须同时配置四点:auto_increment_increment全局统一为2、auto_increment_offset错开(A=1/B=2)、innodb_autoinc_lock_mode=0、log_slave_updates=ON;还需设replicate-same-server-id=0防循环复制,否则INSERT/UPDATE/DELETE均可能引发主键重复或静默数据错误。

auto_increment_offset 和 auto_increment_increment 配不全就必撞主键
只设 auto_increment_offset=1 和 auto_increment_offset=2,却不统一设 auto_increment_increment=2,INSERT 就会重复生成 1、2、3……最终在同步时爆 Duplicate entry '1001' for key 'PRIMARY'。更隐蔽的是:漏掉 innodb_autoinc_lock_mode=0,遇到 INSERT INTO t SELECT ... 会跳号、错号;漏掉 log_slave_updates=ON,本机 relay 日志不写 binlog,双向链路直接断裂。
必须同时满足这四点:
-
auto_increment_increment全局统一(如都为 2) -
auto_increment_offset错开(A=1,B=2) -
innodb_autoinc_lock_mode=0(禁用“交错模式”) -
log_slave_updates=ON(确保 relay 事件能再发出去)
replicate-same-server-id=0 不设就会循环复制
双主不是两个独立主从,而是 A→B + B→A 的闭环。若没关回环,A 写一条记录,B 同步后又把这条 binlog 发回 A,A 再执行一次——结果可能是主键冲突、计数翻倍、或 UPDATE 被执行两遍。MySQL 8.0+ 必须显式配 replicate-same-server-id=0(5.7 是 replicate_same_server_id=0),且两台都要设。仅靠 binlog_do_db 或 server-id 差异无法拦截,它只认 server-id 是否匹配自己。
典型症状:
-
SHOW REPLICA STATUS\G中Seconds_Behind_Master: NULL -
Last_SQL_Error显示主键重复,但错误日志里只有模糊的Relay log read failure - 业务上某条记录被多加了 100 元,查 binlog 却只有一条 UPDATE
UPDATE/DELETE 比 INSERT 更危险,因为不报错也能错
INSERT 至少会被唯一键拦住并中断复制;UPDATE 和 DELETE 却常常静默生效——比如两端并发执行 UPDATE users SET balance = balance + 100 WHERE id = 123,最终 balance 只加了一次;又比如 DELETE FROM logs WHERE created_at ,因时区或延迟,两边删的行集不同,且无任何错误提示。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
真正可控的做法是放弃“让数据库自动协调”,转而由应用控制:
- 所有写操作带条件:例如
UPDATE t SET status='done', version=version+1 WHERE id=? AND version=? - 物理删除全部改为
UPDATE ... SET is_deleted=1, deleted_at=NOW() - 禁止无 WHERE 的
UPDATE或DELETE,DDL 操作必须停写窗口内执行
GTID 模式下双主不能混用 STATEMENT 和 ROW 格式
MySQL 8.4 默认强制 GTID,gtid_mode=ON 和 enforce_gtid_consistency=ON 必须启用,否则 CHANGE REPLICATION SOURCE TO MASTER_AUTO_POSITION=1 直接失败。此时若一台用 binlog_format=STATEMENT,另一台用 ROW,事务在反向同步时可能因函数(如 NOW()、UUID())或临时表行为不一致,导致数据分叉。
必须统一设为 binlog_format=ROW,并确认:
- 所有表都有显式主键(无主键表在 ROW 模式下复制不可靠)
- 禁用
REPLACE INTO和无条件INSERT IGNORE(它们在双主下语义模糊) -
slave_preserve_commit_order=ON(防止事务回放顺序错乱)
双主架构最易被忽略的点是:它根本不判断“哪边更新更合理”,只负责“把语句原样执行一遍”。冲突不是配置不到位才发生,而是只要允许任意写入,就注定会发生——区别只在于是否立刻暴露、是否可逆。所以真正的防线永远在应用层路由和幂等设计,不在 my.cnf 里多加两行参数。

















