确认auto-inc锁卡住插入需观察:show processlist中大量线程状态为waiting for table level lock或waiting for auto-inc lock,慢日志insert耗时骤增,cpu被innodb_autoinc_lock相关函数占满,且show engine innodb status的transactions部分显示waiting for auto-inc lock on表名。

怎么确认是AUTO-INC锁在卡住插入
别急着改参数,先看现象是否匹配:如果 SHOW PROCESSLIST 里大量线程状态是 Waiting for table level lock 或 Waiting for auto-inc lock,慢日志中 INSERT 耗时从几毫秒跳到几百毫秒甚至秒级,QPS 上不去但 CPU 被 innodb_autoinc_lock 相关函数吃满,就大概率是它。
更直接的证据是查 SHOW ENGINE INNODB STATUS 的 TRANSACTIONS 部分,出现类似 waiting for auto-inc lock on t_orders 的描述;或者查 performance_schema.data_lock_waits,能看到锁等待链指向 AUTO_INC 类型。
哪些INSERT语句最容易触发AUTO-INC表级锁
不是所有 INSERT 都一样。真正会全程持表级锁的是以下三类:
-
INSERT INTO t SELECT ...(哪怕只查出10行) -
REPLACE INTO t SELECT ...(含隐式删除+插入) -
INSERT INTO t VALUES (1,'a'), (NULL,'b')(mixed-mode:显式ID混NULL)
注意:INSERT ON DUPLICATE KEY UPDATE 看似简单,但在唯一键冲突路径下可能退化为 bulk 行为;LOAD DATA INFILE 默认也走 bulk 路径。而纯 INSERT INTO t VALUES (),(),()(全 NULL 或全显式)才属于 simple insert,在 innodb_autoinc_lock_mode = 2 下可无锁。
为什么设了innodb_autoinc_lock_mode=2还是卡
因为 mode=2 只对 simple insert 生效,其他两类仍强制走语句级锁:
-
INSERT SELECT无论多小,InnoDB 都不走轻量路径 -
mixed-mode插入会触发内部重试和锁升级,mode=2 下反而开销更大 - 没配
binlog_format = ROW就设 mode=2,主从复制可能丢数据或中断,线上不敢开
所以看到 INSERT SELECT 还在排队,不是参数没生效,是你写的语句本身就不适配 mode=2。
绕过自增锁瓶颈的实操动作
比调参更有效的是改写法:
- 把大
INSERT INTO t SELECT FROM s WHERE ...拆成应用层分页 + 批量VALUES:每次 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') - 大批量导入时临时关唯一性检查:
SET UNIQUE_CHECKS=0,导入完再SET UNIQUE_CHECKS=1并ANALYZE TABLE
最容易被忽略的是:业务代码里硬写 id + 1 就是下一条,或用 id BETWEEN 1000 AND 1010 做拉取——mode=2 下跳号会直接漏数据,这种依赖必须提前清理。











