
自增步长怎么设才不撞车
双主架构下,AUTO_INCREMENT 必须错开,否则两个节点同时插入会生成相同主键,直接报 Duplicate entry 错误。不是设个 auto_increment_increment 就完事——得和 auto_increment_offset 配合用,且两台机器值必须互斥。
-
auto_increment_increment设为 2(或更大,取决于节点数),表示每次自增的跨度 -
auto_increment_offset在主1上设为 1,在主2上设为 2(若只有两节点);三节点则分别设 1/2/3,增量也得同步改成 3 - 这两个参数必须写进
my.cnf的[mysqld]段,并重启生效;仅用SET GLOBAL临时改,实例重启后丢失,双主切回来就可能冲突 - 注意:如果已有表用了
AUTO_INCREMENT,改参后新插入不会“跳过”已存在值,但只要 offset 不重叠,后续分配就不会重
双主写入前必须关掉 auto-increment 相关风险项
MySQL 双主默认不禁止双向写入,但 auto_increment 只是冰山一角。真正要命的是复制线程不校验主键冲突、也不自动跳过重复错误——一旦写入同一条 id,从库 SQL 线程立刻停住,报错 ERROR 1062 (23000): Duplicate entry 'X' for key 'PRIMARY'。
- 务必在每台主库上执行:
SET GLOBAL sql_log_bin = OFF;再手动执行写操作(如维护脚本),避免误写进 binlog - 不要依赖
INSERT IGNORE或ON DUPLICATE KEY UPDATE来“兜底”——它们只对单条语句有效,无法解决并发插入时的竞态 - 检查
show slave status\G中的Seconds_Behind_Master和SQL_Remaining_Delay,延迟高时写入另一主库风险指数上升 - 禁用
innodb_autoinc_lock_mode = 2(交错模式)在双主中很危险,它会让批量插入(如INSERT ... SELECT)生成不可预测的 ID 序列
验证自增配置是否真生效
改完配置别急着上线,先确认两台机器的 auto_increment_increment 和 auto_increment_offset 值一致且符合规划,否则白配。
- 连上每台 MySQL,执行:
SELECT @@auto_increment_increment, @@auto_increment_offset; - 建一张测试表:
CREATE TABLE test_inc (id INT PRIMARY KEY AUTO_INCREMENT) ENGINE=InnoDB; - 在主1插入 3 行,查
SELECT id FROM test_inc;—— 应得 1,3,5;主2同样操作应得 2,4,6 - 如果某台出现连续 ID(如 1,2,3),说明
offset没生效,大概率是没重启 mysqld 或配置写错段落(比如写到[client]下了)
为什么不能只靠应用层分 ID 段
有人想让应用自己控制:A 服务只写奇数 ID,B 服务只写偶数。这看似绕开了数据库配置,实则埋雷更深。
- 应用无事务跨库能力,一旦 A 服务写主1失败、转写主2,ID 段规则立刻崩坏
- 运维扩缩容时,ID 分段逻辑要同步改所有服务代码,而数据库参数只需改配置+重启
- 备份恢复后,
SHOW CREATE TABLE显示的AUTO_INCREMENT值是当前最大 ID+1,但应用层不知道这个偏移,续写极易重复 - 中间件(如 MyCat、ShardingSphere)若做分库分表,其路由规则和 MySQL 自增机制容易互相干扰,调试成本远高于调两个系统变量
真正难的不是设那两个参数,而是确保所有写入口(包括定时任务、DBA 手动 SQL、ETL 工具)都严格遵守主库角色划分——这点,永远比配置本身更易出问题。










