innodb_autoinc_lock_mode 是控制 mysql 自增 id 插入时加锁行为的参数,影响并发性能与 id 连续性;默认值 1 平衡安全与性能,0 已弃用,2 需 row 格式 binlog 且跳号不可避免。

innodb_autoinc_lock_mode 是什么,为什么改它
这个参数控制 MySQL 在插入自增 ID 时的加锁行为,直接影响并发插入性能和 ID 分配的连续性。默认值是 1(“连续”模式),但高并发批量插入(比如 INSERT ... SELECT、REPLACE、LOAD DATA)时容易卡住,或出现 ID 跳号——这不是 bug,是设计使然。
想让自增 ID 尽量紧凑、减少锁等待?得调它;想吞吐优先、能接受跳号?默认就行。关键是别在没理解场景时盲目设成 0 或 2,否则主从不一致或 binlog 复制失败的风险会立刻浮现。
三种取值的实际影响和适用场景
0(传统模式):全表级 AUTO_INC 锁,每次插都等,ID 绝对连续,但并发极低。只在老版本兼容或极特殊审计要求下用,现在基本不用。
1(默认,连续模式):普通 INSERT 用轻量锁,批量语句(如 INSERT INTO t SELECT ...)仍会预分配一段 ID 并加表锁。平衡了性能和可预测性,主从复制安全(statement-based 和 row-based 都 OK)。
2(交错模式):所有插入都不加表锁,ID 分配完全交错,性能最高,但 ID 必然跳号,且 仅支持 row-based binlog 格式。如果 binlog_format 还是 STATEMENT,直接报错 ERROR 1665 (HY000): Cannot execute statement: binlogging impossible。
无序列表说明:
- 线上 OLTP 系统,用
1最稳妥,别为了省几个 ID 冒险切2 - 纯写入密集的 ETL 导入场景,确认
binlog_format = ROW后,可设为2 -
0已被官方标记为 deprecated,MySQL 8.0+ 不再推荐,配置后启动会警告
怎么改,以及改完必须检查什么
改法很简单,在 my.cnf 的 [mysqld] 段加一行:innodb_autoinc_lock_mode = 1,然后重启 mysqld。但重启不是终点——你得验证它真生效了,且没埋雷。
检查步骤:
- 连上 MySQL 执行
SELECT @@innodb_autoinc_lock_mode;,确认返回值是你设的数字 - 查当前 binlog 格式:
SELECT @@binlog_format;,若想用2,这里必须是ROW - 看 error log 是否有警告,比如
Setting innodb_autoinc_lock_mode=0 is deprecated或复制相关报错 - 如果用了 GTID 或 MGR,
2模式没问题;但传统异步复制 +STATEMENT,绝对不能设2
自增 ID “预留”其实是误解,真正要管的是初始化值和增长步长
很多人说“预留 ID”,其实想的是避免自增列从 1 开始,或者跳过某段数字。但 innodb_autoinc_lock_mode 不管这个——它只管“怎么锁、怎么分”。真要跳过前 N 个 ID,得靠 ALTER TABLE t AUTO_INCREMENT = 10000;;想让每次增长不止 +1,得设 auto_increment_increment 和 auto_increment_offset(多主环形复制才需要)。
注意:AUTO_INCREMENT 值不会自动回退,即使删光数据也不会重置;手动 ALTER 修改它时,新值必须大于当前最大 ID,否则会被静默忽略(MySQL 5.7+ 会报 warning)。
最容易被忽略的一点:InnoDB 表的自增值是存在内存里的,不是实时刷盘。实例异常重启后,它会扫描索引找最大值再加一——所以极端情况下可能“倒退”或重复,但概率极低;如果你依赖自增 ID 做业务排序或幂等判断,这本身就是危险设计。











