MySQL Insert Intention Lock 插入意向锁是什么

MySQL锁系列|插入意向锁完整详解

前置阅读:Gap间隙锁、Next‑Key Lock临键锁

一、什么是插入意向锁 Insert Intention Lock

插入意向锁是 InnoDB 在执行 INSERT 插入前自动施加的一种特殊的间隙锁(Gap Lock)

⚠️注意:名字带"意向",它不是表级的 IS/IX意向锁 ,属于行锁体系,作用于索引间隙。

生效前提:InnoDB、RR可重复读隔离级别;RC隔离级别关闭Gap锁,也就不存在插入意向锁。

作用:标记当前事务打算在某个索引间隙插入新数据

  • 多个事务向同一个间隙插入不同索引值时,插入意向锁互相兼容,可以并发插入,不会互相阻塞,提升插入并发性能。
  • 如果该间隙已经被其他事务持有 Gap间隙锁 / Next‑Key临键锁,插入意向锁会被阻塞,必须等待间隙锁释放,以此保护幻读不发生。

二、触发时机

执行INSERT语句时,InnoDB内部流程:

  1. 定位待插入记录在B+树索引中的间隙位置
  2. 尝试获取该间隙的插入意向锁
  3. 如果间隙被Gap/Next‑Key锁占用,INSERT阻塞等待;间隙空闲则获取成功
  4. 成功之后,对真正插入的数据行,加Record X排他行锁
  5. 事务提交,锁全部释放

普通快照读SELECT不会产生;UPDATE / DELETE / SELECT ... FOR UPDATE也不会产生插入意向锁,只有INSERT才会生成

三、锁兼容性矩阵

锁类型 插入意向锁 Gap间隙锁 / Next‑Key临键锁 Record S/X行锁
插入意向锁 ✅兼容 ❌互斥阻塞 ✅兼容

重点理解两点:

  1. 插入意向锁与插入意向锁互相兼容:多个事务可以同时拿到同一个间隙的插入意向锁,只要插入主键/索引值不一样,可以并发插入成功,不会阻塞。
  2. 插入意向锁 和 Gap锁、Next‑Key临键锁互斥:只要间隙被别人加了间隙锁,所有INSERT往这个间隙插入全部阻塞等待,这是RR防止幻读的核心机制。

示例:索引已有 1,5,间隙 (1,5)

  • 事务A:插入 id=2
  • 事务B:插入 id=3
    两个事务同时获取间隙(1,5)的插入意向锁,互不阻塞,可以同时完成插入。

如果事务C先执行select ... for update,给间隙(1,5)加上Gap锁;那么A、B的INSERT全部阻塞。

四、实战演示

测试表

sql 复制代码
CREATE TABLE t_lock(
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(32)
);
INSERT INTO t_lock(name) VALUES('A'),('E');
-- id:1,5;间隙 (1,5)

场景1:间隙持有临键锁,INSERT被阻塞

会话A

sql 复制代码
BEGIN;
-- id=2不存在,唯一索引等值查询查无数据,退化为Gap锁,锁住间隙 (1,5)
SELECT * FROM t_lock WHERE id=2 FOR UPDATE;

此时间隙(1,5)被加上Gap间隙锁。

会话B

sql 复制代码
BEGIN;
-- 尝试插入id=3,需要获取间隙(1,5)插入意向锁,和Gap锁冲突,直接阻塞
INSERT INTO t_lock(id,name) VALUES(3,'C');

查看锁信息:

sql 复制代码
SELECT ENGINE_TRANSACTION_ID,LOCK_TYPE,LOCK_MODE,LOCK_TABLE,LOCK_DATA
FROM performance_schema.data_locks;
  • 会话A锁:LOCK_MODE: X,GAP Gap间隙锁
  • 会话B锁:LOCK_MODE: X,INSERT_INTENTION 插入意向锁,状态为WAITING等待中

会话A执行COMMIT;释放Gap锁,会话B立刻完成插入。

场景2:同一间隙,多个INSERT并发插入互不阻塞

会话A:

sql 复制代码
BEGIN;
INSERT INTO t_lock(id,name) VALUES(2,'B');

会话B:

sql 复制代码
BEGIN;
INSERT INTO t_lock(id,name) VALUES(3,'C');

A、B都获取间隙(1,5)插入意向锁,互相兼容,不会阻塞,两个insert都正常执行。

只有插入完全相同唯一键值时,才会报唯一键冲突报错,这是约束校验,不是锁阻塞。

五、RC隔离级别下没有插入意向锁

RC读已提交隔离级别:

  1. Gap间隙锁、Next‑Key临键锁全部关闭
  2. 插入意向锁也随之消失
  3. INSERT只会对插入行加Record X记录锁,间隙没有任何锁保护
  4. 并发插入性能更高,但当前读会出现幻读现象。

很多生产环境把隔离级别改为RC,就是为了消除Gap锁+插入意向锁带来的大量INSERT阻塞问题。

六、线上典型坑点与死锁案例

坑1:看不到insert语句,但是大量insert阻塞等待

现象:业务大量INSERT慢、堆积,但是没有慢SQL,也没有update/delete长事务。

根因:某个长事务执行for update / update / delete产生Gap锁/Next‑Key锁,锁住索引间隙,所有落在该间隙的INSERT全部等待插入意向锁释放。

✅排查:查询performance_schema.data_locks看是否存在X,GAP间隙锁,找到持有Gap锁的长事务。

坑2:插入意向锁参与死锁(经典死锁场景)

复现流程:

表数据 id:1, 10

会话A:

sql 复制代码
BEGIN;
SELECT * FROM t_lock WHERE id=5 FOR UPDATE; -- 查无数据,加Gap锁 (1,10)

会话B:

sql 复制代码
BEGIN;
INSERT INTO t_lock(id,name) VALUES(3,'B'); -- 获取插入意向锁,等待A释放Gap锁

会话A:

sql 复制代码
INSERT INTO t_lock(id,name) VALUES(4,'A'); -- A现在尝试插入4,也需要获取本间隙插入意向锁,等待B

循环等待:B等A的Gap锁;A等B的插入意向锁 → 触发死锁,InnoDB自动回滚其中一个事务
关键点:同一个事务,自己持有某个间隙Gap锁,自己也不能往这个间隙做INSERT,同样会等待,产生死锁。

坑3:误以为INSERT不会加锁

INSERT不是完全无锁:RR下INSERT会加插入意向锁,同时对新行加X记录锁;长事务不commit,插入的行X锁也会持续持有。

七、常见误区澄清

❌误区1:插入意向锁是表级IS/IX意向锁

完全两码事。IS/IX是表锁层面;插入意向锁属于行锁‑间隙锁体系。

❌误区2:插入意向锁会阻塞其他INSERT

插入意向锁之间互相兼容;只有遇上Gap锁、临键锁才阻塞。

❌误区3:RC隔离级别也会产生插入意向锁

RC关闭Gap锁机制,不会产生插入意向锁。

❌误区4:INSERT一定会产生插入意向锁

INSERT需要定位到索引间隙才会生成;RC模式无;如果索引不存在间隙,也不会触发。

❌误区5:同一个事务持有Gap锁,可以直接往该间隙INSERT

不行,自己持Gap锁,自己INSERT同样需要获取插入意向锁,会等待,极易死锁。

八、总结

  1. Insert Intention Lock插入意向锁,是RR级别下INSERT产生的特殊间隙锁,标记事务有插入意图,RC隔离级别不存在。
  2. 插入意向锁之间互相兼容,支持多事务同一间隙并发插入不同索引值,提升插入性能;但与Gap锁、Next‑Key临键锁互斥。
  3. 核心职责:兼顾并发插入性能,同时配合Gap锁阻止幻读;间隙一旦被Gap锁锁住,所有INSERT全部阻塞。
  4. 线上故障特征:大量INSERT阻塞等待,根源往往是长事务产生了Gap/Next‑Key锁;同一个事务持有Gap锁又执行INSERT会触发死锁。
  5. 优化方案:优先使用RC隔离级别消除间隙锁体系;避免长事务执行当前读(for update/update/delete)缩小锁范围;加锁SQL尽量走唯一索引,触发锁退化减少Gap锁产生。

MySQL锁系列全部完结:全局锁、MDL元数据锁、S表读锁、X表写锁、IS意向共享锁、IX意向排他锁、Record S/X行锁、Gap间隙锁、Next‑Key临键锁、Insert Intention插入意向锁。

相关推荐
Nontee9 小时前
MySQL 插入冲突了怎么办?两种处理方式入门笔记
数据库·笔记·mysql
ltl9 小时前
Parquet 文件格式:row group、编码与谓词下推索引
数据库
ltl9 小时前
PostgreSQL Join 路径:优化器如何选中 Nested Loop
数据库
ltl10 小时前
RocksDB 生产嵌入:Flink、TiKV 与 Kafka Streams 怎么用
数据库
devilnumber11 小时前
MySQL 性能优化・诗意化记忆
数据库·mysql·性能优化
瀚高PG实验室12 小时前
PostgreSQL pg_basebackup 和 pg_rewind 可覆盖源端超级用户选择的无关文件HGVE-2026-E010
数据库·postgresql·瀚高数据库
宠友信息13 小时前
社区类源码开发实践中的仿小红书系统技术要点分析
java·spring boot·redis·mysql·uni-app·vue·内容运营
OceanBase数据库官方博客14 小时前
亮相“十五五”公积金高质量发展大会“AI 数据库”助力智慧公积金升级
数据库·人工智能
Lyra_Infra14 小时前
MySQL Docker 误删恢复:binlog PITR
mysql·docker·命令行