mysql 5.7默认innodb_autoinc_lock_mode=1是插入吞吐瓶颈主因:简单插入用轻量mutex,但insert...select等批量语句全程持表级auto-inc锁,阻塞所有并发insert,且事务回滚、主从复制冲突会进一步加剧等待与不一致。

innodb_autoinc_lock_mode = 1 是默认瓶颈源
MySQL 5.7 默认启用 innodb_autoinc_lock_mode = 1(“连续模式”),它在“简单插入”(如 INSERT INTO t VALUES (...))时用轻量级 mutex 分配自增值,看似高效,但对批量插入语句(如 INSERT ... SELECT、REPLACE INTO、LOAD DATA)仍会升级为表级 AUTO-INC 锁——整个语句执行期间独占该锁,其他插入全部阻塞。这在高并发写入场景下极易形成排队链,TPS 断崖式下跌。
事务回滚 + 批量插入 = 双重锁等待
当一个带 INSERT ... SELECT 的事务正在执行,同时另一个事务因唯一键冲突或逻辑异常回滚,InnoDB 不仅要释放行锁,还会在释放 AUTO-INC 锁前完成自增计数器的跳变与清理。此时新来的插入请求既等不到锁,又无法预判下一个可用 ID,只能空转等待。实测中,这种组合会让平均延迟从 1ms 拉升至 15ms+,且错误日志里几乎不报错,只表现为“写入变慢”。
主从复制加剧锁竞争失衡
MySQL 5.7 的 REPLACE INTO 在主库执行时会触发自增 ID 预分配并写入 binlog,但从库回放时若遇到主键冲突(比如因延迟导致同一条记录被重复写入),会跳过插入但自增值已前进——造成从库 AUTO_INCREMENT 值落后于主库。一旦发生主从切换,新主库因自增值偏小,立刻出现 Duplicate entry 'XXX' for key 'PRIMARY' 报错。这不是锁本身的问题,而是锁机制 + 复制行为共同放大了不一致风险。
为什么不能直接切到 mode = 2?
innodb_autoinc_lock_mode = 2(交错模式)确实能消除非事务性插入的锁等待,但它要求 binlog_format = ROW,且不兼容某些旧业务的语句逻辑(比如依赖自增 ID 连续性做分页或导出)。更重要的是:它无法解决事务内多条插入语句之间的自增 ID 竞争——只要事务里有两条 INSERT,第二条仍可能因第一条已占用 mutex 而短暂等待。真正要解耦,得把 ID 生成逻辑移出数据库。
自增 ID 的“锁瓶颈”本质不是锁太重,而是它把分布式协调问题强行压进单点存储引擎里。哪怕调成 mode = 2,只要业务还在用 AUTO_INCREMENT 当全局标识,就躲不开重启、回滚、复制延迟带来的 ID 不可预测性——这点在微服务拆分后尤其致命。











