直接改innodb_autoinc_lock_mode=2仅对insert into t values()类简单插入生效,对insert select、replace select等批量/混合插入仍需语句级锁;应优先拆分大查询为分页批量插入、用insert on duplicate key update替代replace,并确保binlog_format=row且业务不依赖id连续性。

直接改 innodb_autoinc_lock_mode = 2 能显著缓解锁争用,但只对 INSERT INTO t VALUES () 类简单插入生效;如果你的业务大量使用 INSERT INTO t SELECT 或 REPLACE INTO t SELECT,调这个参数根本没用——卡点不在参数,而在语句本身。
怎么确认真是 AUTO-INC 锁在卡住你
别一上来就改配置。先看现象是否匹配:
-
SHOW PROCESSLIST里大量线程状态是Waiting for table level lock - 慢日志里
INSERT耗时突增(尤其带SELECT、REPLACE、LOAD DATA的语句),但EXPLAIN显示执行计划正常 - QPS 上不去,CPU 却被
innodb_autoinc_lock相关函数吃满 -
SHOW ENGINE INNODB STATUS的TRANSACTIONS部分出现AUTO_INC锁等待
为什么 innodb_autoinc_lock_mode = 2 开了还是卡
因为 mode=2 只跳过 Simple inserts 的锁,其他两类仍要锁:
-
Bulk inserts(如
INSERT INTO t SELECT、LOAD DATA INFILE):mode=2 下依然退化为语句级锁,执行多久锁多久 -
Mixed-mode inserts(如
INSERT INTO t VALUES (100,'x'), (NULL,'y')):显式 + 隐式混用,也会触发锁 - 即使开了 mode=2,只要语句里含
SELECT,InnoDB 就不走轻量路径
所以看到 INSERT SELECT 还在排队,不是参数没生效,是你写法本身就不适配 mode=2。
不改参数,怎么绕过自增锁瓶颈
真正压垮并发的常是写入模式本身。优先从 SQL 写法入手:
- 把大
INSERT INTO t SELECT FROM s WHERE ...拆成应用层分页 + 批量多值插入,每批控制在 500–1000 行:INSERT INTO t VALUES (),(),()... - 用
INSERT ... ON DUPLICATE KEY UPDATE替代REPLACE INTO:前者只在真正插入新行时才推进自增计数器,更省 ID、更少锁 - 避免在 mode=2 下混用显式 ID 和
NULL,比如INSERT INTO t VALUES (100, 'x'), (NULL, 'y')—— 这种写法会强制降级为语句级锁 - 确保
binlog_format = ROW:否则 mode=2 启动会报错或降级警告,主从复制也可能中断
最易被忽略的是:mode=2 下的 ID 分配不可预测。如果你的应用层做了“插入后立刻用刚生成的 ID 做关联查询”并假设它紧邻前一个 ID,这种逻辑会失效;某些分库分表中间件依赖 ID 的单调递增性做路由,切换前务必确认兼容性。











