必须配对设置auto_increment_increment和auto_increment_offset,否则双主写入必然触发ERROR 1062;因MySQL默认两节点均increment=1、offset=1,各自生成1,2,3…,同步时ID重复导致复制中断。

必须设 auto_increment_increment 和 auto_increment_offset,否则双主写入必然触发 ERROR 1062 (23000): Duplicate entry 'X' for key 'PRIMARY'
为什么默认配置在双主下一定会冲突
MySQL 默认 auto_increment_increment = 1、auto_increment_offset = 1,两台主库各自独立生成自增 ID,都从 1 开始、每次 +1 → 都插 id=1、id=2、id=3。一旦任一端插入后同步到对面,另一端本地已有同 ID 行,复制直接报错中断。
这不是“偶尔发生”,而是只要两边都执行过 INSERT,就 100% 触发。哪怕只有一边写,另一端若重启、重连或手动执行过 INSERT,也极可能撞上。
正确配置值与生效方式
核心是让两台机器生成的 ID 序列天然互斥:
- 主库 A:
auto_increment_increment = 2、auto_increment_offset = 1→ 生成1, 3, 5, … - 主库 B:
auto_increment_increment = 2、auto_increment_offset = 2→ 生成2, 4, 6, …
这两项必须写进 /etc/my.cnf 的 [mysqld] 段,且重启 mysqld 才生效。运行时用 SET GLOBAL 修改只影响新连接,复制线程仍按旧值生成 ID,无效。
验证是否生效:连上每台库执行 SELECT @@auto_increment_increment, @@auto_increment_offset;;再建测试表 CREATE TABLE test_inc (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB;,各插 3 行,A 应得 1,3,5,B 应得 2,4,6。若出现连续 ID(如 1,2,3),说明配置没加载或没重启。
扩容到三主或更多时怎么改
加第三台主库不是简单复制现有配置,必须提前重构整个自增序列:
- 把所有主库的
auto_increment_increment改为3 - 三台分别设
auto_increment_offset = 1、2、3 - 已存在的表需人工对齐
AUTO_INCREMENT值,例如原 A 最大 ID 是 99,就得ALTER TABLE tbl AUTO_INCREMENT = 100,确保下一个生成的是 100(即 1 + 3×33)
如果没提前改 increment 就加第三台,新库和旧库会同时生成 1,4,7,… 和 2,5,8,…,但第三台也从 1 开始 → 必然重复。
仅靠自增步长不能解决所有冲突
它只防 INSERT 主键碰撞,对以下场景完全无效:
-
UPDATE users SET balance = balance + 100 WHERE id = 123:两端并发执行,结果取决于 apply 顺序 -
DELETE FROM logs WHERE created_at < '2026-01-01':两边都删,可能多删或漏删 - 应用先
SELECT再UPDATE,中间另一端已改该行 → 覆盖而非合并
真正关键的不是参数本身,而是写入控制策略:按业务拆分写入(如 user 表全走 A,order 表全走 B),所有 UPDATE/DELETE 加幂等条件(如 WHERE version = ?),删除操作统一转为软删。这些没法靠 SQL 配置,得改应用路由逻辑或加中间件规则。


















