mysql自增主键锁竞争是很多业务在高频插入场景下会遇到的性能瓶颈,innodb引擎提供的innodb_autoinc_lock_mode参数可以从锁策略层面优化这个问题,不同的参数取值对应不同的自增锁控制逻辑,适配不同的插入场景需求。

innodb_autoinc_lock_mode参数基础说明
innodb_autoinc_lock_mode是innodb引擎的动态参数,用于决定自增主键的锁获取和释放时机,取值分为0、1、2三个档位,默认值为1。自增锁是一种特殊的表级锁,用于保证自增列的值分配是连续且唯一的,不同模式下锁的持有时间和并发能力有明显差异。
三种参数取值的锁行为差异
取值为0:传统模式
这个模式下所有的插入语句都会获取表级自增锁,语句执行结束后才释放锁,不管插入语句的类型是什么。锁的持有时间最长,并发插入能力最差,但是可以保证所有的自增值都是绝对连续的,不会出现空洞。
-- 查看当前innodb_autoinc_lock_mode参数值 SHOW VARIABLES LIKE 'innodb_autoinc_lock_mode';
取值为1:连续模式(默认)
这个模式会区分简单插入和批量插入两种场景。简单插入指的是提前知道插入行数的语句,比如普通的INSERT语句、REPLACE语句,这类语句会在分配自增值的时候获取自增锁,分配完成后立刻释放,不需要等语句执行结束。批量插入指的是提前不知道插入行数的语句,比如INSERT ... SELECT、LOAD DATA语句,这类语句会获取自增锁,语句执行结束后才释放。这个模式在保证自增值连续的前提下,提升了简单插入的并发能力。
取值为2:交错模式
这个模式下所有插入语句都不会获取表级自增锁,自增值的分配是通过互斥量控制的,多个语句可以并行分配自增值,并发能力最强。但是这个模式不能保证自增值是连续的,可能会出现自增空洞,而且如果binlog格式是STATEMENT的话,会导致主从数据不一致,因此这个模式要求binlog格式必须是ROW。
| 参数取值 | 锁持有策略 | 自增值连续性 | 并发插入能力 | 适用场景 |
|---|---|---|---|---|
| 0 | 所有语句执行完释放锁 | 绝对连续 | 差 | 对自增值连续性要求极高,并发插入量低的场景 |
| 1 | 简单插入分配完值释放,批量插入执行完释放 | 连续 | 中等 | 大部分常规业务场景,默认选择 |
| 2 | 无表级自增锁 | 可能不连续 | 强 | 高并发插入,对自增值连续性无要求,binlog为ROW格式的场景 |
参数调整方法
如果是临时调整,可以直接通过SQL语句修改,重启mysql后会恢复默认值:
-- 设置参数为2,临时生效 SET GLOBAL innodb_autoinc_lock_mode = 2;
如果需要永久生效,需要修改mysql的配置文件my.cnf,在[mysqld]节点下添加配置,之后重启mysql服务:
[mysqld] # 设置自增锁模式为2 innodb_autoinc_lock_mode=2
调整时的注意事项
- 如果业务对自增主键的连续性有严格要求,比如自增值需要作为业务编号对外展示,不要选择取值2,避免出现自增空洞。
- 选择取值2的时候,必须确认binlog格式是ROW,否则会导致主从复制数据不一致。
- 调整参数前建议先在测试环境验证,观察插入性能的变化和自增值的分配情况,确认符合业务预期再应用到生产环境。
- 如果业务中大量使用批量插入语句,取值1和取值0的锁竞争差异不大,需要结合其他优化手段,比如降低批量插入的单次数据量。
额外优化建议
调整innodb_autoinc_lock_mode只是优化自增锁竞争的一个手段,还可以结合其他方案进一步提升性能:
- 如果业务不需要自增主键,可以使用UUID或者雪花算法生成分布式ID,从根源上避免自增锁的问题。
- 控制单条插入语句的数据量,避免单次插入过多数据导致锁持有时间过长。
- 尽量使用简单插入语句,减少INSERT ... SELECT这类批量插入语句的使用频率。
mysql自增主键锁竞争innodb_autoinc_lock_mode修改时间:2026-06-27 06:27:26