双主架构中,auto_increment_increment与offset须成对配置:increment设为N,各节点offset取1~N互异值;同时必须配置唯一server_id、开启ROW格式binlog,否则同步失败。

auto_increment_increment 和 auto_increment_offset 必须成对设置
只改步长不调 offset,或者反过来,都会导致双主写入时主键重复。MySQL 的自增逻辑是:next_id = (current_max + offset - 1) % increment + 1 这样的伪公式并不准确,真实行为是:每个新插入的 ID 由当前最大值、auto_increment_offset 和 auto_increment_increment 共同决定,但关键在于——两台机器必须用相同 auto_increment_increment、不同 auto_increment_offset,且 offset 值必须落在 [1, increment] 范围内。
常见错误现象:
- 主库 A 插入成功,主库 B 同步时报
Duplicate entry '5' for key 'PRIMARY' - 重启 MySQL 后自增 ID “跳变”,比如上次是 7,重启后变成 9 或 10(因为 offset 在 server 启动时参与初始化)
实操建议:
- 双主场景下,
auto_increment_increment固定设为2,A 设auto_increment_offset = 1,B 设auto_increment_offset = 2 - 三主则 increment =
3,offset 分别为1、2、3 - 务必在
[mysqld]段落中静态配置,不要依赖运行时SET GLOBAL—— 重启后失效,且某些版本(如 MySQL 8.0.33+)会忽略会话级设置对新建表的影响
my.cnf 配置必须包含 server_id 和 binlog 设置
仅设自增参数,同步仍会失败。MySQL 双主依赖 binlog 复制,而复制要求每个节点有唯一 server_id,且必须开启 binlog 并配置格式。
容易踩的坑:
-
server_id写成 IP 地址或主机名(如server_id = mysql-master1)—— 必须是纯数字,且全局唯一 - 遗漏
log-bin或用了错误路径(如log-bin = /var/lib/mysql/mysql-bin但目录无写权限) -
binlog_format设为STATEMENT—— 在涉及函数、临时表、非确定性语句时极易导致主从不一致,推荐MIXED或ROW
最小可行配置片段(Master A):
server_id = 101 log-bin = mysql-bin binlog_format = ROW sync_binlog = 1 auto_increment_increment = 2 auto_increment_offset = 1
Master B 对应改为 server_id = 102 和 auto_increment_offset = 2。
已有数据的表不能靠配置自动“修复”ID序列
配置生效只影响后续 INSERT,不会重排现有记录的主键。如果双主搭建前表里已有 ID=1~100 的数据,那么即使设置了 offset=1/increment=2,下一条插入也未必是 101 —— 它取决于当前 MAX(id) 和内部自增计数器状态。
使用场景注意点:
- 新表:配置生效及时,行为可预测
- 旧表:首次插入前建议手动执行
ALTER TABLE t AUTO_INCREMENT = 101(设为下一个期望奇数/偶数),否则可能生成冲突 ID - 如果表已存在冲突 ID(如两边都插了 id=5),必须先人工清理再启用双主,否则复制线程直接中断
UPDATE/DELETE 无法靠自增配置规避冲突
很多人误以为设好 increment 和 offset 就“万事大吉”。其实它只解决 INSERT 主键重复问题,对并发 UPDATE 或 DELETE 完全无效。例如两端同时执行 UPDATE users SET status = 'active' WHERE id = 123,结果取决于谁先提交、谁后同步,没有原子协调机制。
这意味着:
- 双主双写本质是“最终一致性”,不是强一致
- 业务层必须自己处理更新冲突(比如加 version 字段、用 SELECT FOR UPDATE、或改用幂等设计)
- DDL 操作(如
CREATE DATABASE、DROP TABLE)默认不复制,除非显式配置binlog_do_db或关闭replicate_ignore_db
真正难的从来不是怎么配自增,而是怎么让应用接受“写操作可能被覆盖”这个事实。配置只是把最表层的主键撞车挡住了,底下还有更深的水。


















