innodb_autoinc_lock_mode=1是MySQL 5.7默认的连续模式,区分simple insert(轻量mutex锁)与bulk/mixed insert(持表级AUTO-INC锁至语句结束),兼顾并发与兼容性,但不解决回滚跳号、重启回溯等根本问题。

MySQL 5.7 的自增锁机制本身没变,变化的是默认行为和可配置粒度——innodb_autoinc_lock_mode=1 成为默认值,但模式 0/1/2 的语义、触发条件、并发表现和风险点全部延续自 5.1,并未在 5.7 中新增或删除任何一种锁模式。
innodb_autoinc_lock_mode=1 是什么,为什么它成了 5.7 默认
它叫“连续模式”,不是“无锁”,也不是“完全串行”。核心是区分插入类型做差异化加锁:
-
INSERT INTO t (a) VALUES (1), (2)这类 simple insert:用轻量 mutex 分配 ID,不持表锁,多个事务可并发执行 -
INSERT INTO t SELECT ...这类 bulk insert:仍会持表级AUTO-INC锁,直到语句结束 -
INSERT INTO t (id, a) VALUES (100, 'x'), (NULL, 'y')这类 mixed-mode insert:按 bulk 处理,也会锁表
5.7 选它作默认,是因为它在多数 OLTP 场景下比 mode=0 吞吐高、比 mode=2 兼容性好——但它解决不了重启回溯、事务回滚跳号、主从复制一致性等根本问题。
mode=2 在 5.7 中能用,但必须手动开且验证三件事
mode=2(交错模式)在 5.7 完全支持,但不是“开箱即用”:
- 必须确认
binlog_format是ROW:执行SELECT @@binlog_format,如果是STATEMENT或MIXED,开启 mode=2 会导致主从自增 ID 不一致 - 检查业务是否依赖 ID 连续性:比如用
id BETWEEN 100 AND 110拉取分页,mode=2 下可能跳过 105、107,导致漏数据 - 确认没有混合场景下的隐性冲突:比如定时任务跑
INSERT SELECT(bulk),而日常接口大量发INSERT VALUES(simple),mode=1 已足够,强行上 mode=2 反而让 bulk 插入失去连续性保障
哪些操作仍会触发表级 AUTO-INC 锁,哪怕 mode=1
别被“默认 mode=1 就高并发”误导。以下操作在 5.7 中无论 mode=1 还是 mode=2,只要涉及行数不可预知,就仍会升级为表锁:
-
INSERT INTO t SELECT ... FROM s WHERE ...(哪怕只查出 1 行,InnoDB 也无法在语句开始前确定结果集大小) LOAD DATA INFILEREPLACE INTO t SELECT ...-
INSERT ... ON DUPLICATE KEY UPDATE:当存在唯一键冲突时,内部执行路径可能退化为 bulk 行为,在 mode=1 下同样会锁表
这类语句一旦并发量上去,就会卡住所有其他插入——这不是配置错了,而是语义决定的,没法绕过。
真正容易被忽略的兼容性陷阱
5.7 的自增锁行为看似稳定,但几个底层细节常被误判:
-
SHOW CREATE TABLE和SHOW TABLE STATUS返回的AUTO_INCREMENT=XX值,都是读内存dict_table_struct.autoinc,不是查磁盘;重启后重算MAX(id)+1,所以这个值随时可能“变小”,不能用于监控或告警 -
ALTER TABLE t AUTO_INCREMENT = N在 5.7 中只改内存,重启即失效;想持久化必须升级到 8.0+ -
auto_increment_offset和auto_increment_increment在 5.7.27 之前存在在线修改时主键冲突的修复缺陷,若用集群+滚动升级,得核对 patch 版本
最麻烦的其实是心理预期:很多人调了 innodb_autoinc_lock_mode 就以为“锁没了”,结果发现 bulk 插入还是卡、ID 还是跳、重启后还是回溯——不是参数没生效,而是这些现象本就不归它管。


















