插入意向锁是InnoDB在INSERT前加的特殊间隙锁,不阻塞其他插入意向锁,仅与间隙锁或临键锁冲突,旨在减少并发插入锁冲突、提升吞吐量,但不当使用易引发死锁或锁等待。
插入意向锁(Insert Intention Lock)是 InnoDB 在执行 INSERT 语句前加的一
种特殊间隙锁(Gap Lock),它本身不阻塞其他插入意向锁,只在目标间隙已被其他事务加了互斥的间隙锁或临键锁(Next-Key Lock)时才会等待。它的核心作用是**减少并发插入时的锁冲突,提升写入吞吐量**,但用不好反而会引发死锁或锁等待。
当事务尝试向某个索引间隙(比如 id=5 和 id=10 之间)插入新记录时,InnoDB 不直接加传统间隙锁,而是加一个“插入意向锁”,标记“我打算往这儿插”。这个锁和别的插入意向锁兼容——多个事务可以同时在同一个间隙加插入意向锁,互不阻塞。
但它与以下锁冲突:
例如:事务 A 执行 SELECT * FROM t WHERE id BETWEEN 5 AND 10 FOR UPDATE(没查到数据),会在 (5,10) 加间隙锁;此时事务 B 插入 id=7 就会被阻塞,因为其插入意向锁与该间隙锁冲突。
常见于高并发写入、主键/唯一键分布密集、且存在范围锁操作的场景:
关键思路是:**避免让插入意向锁撞上不必要的间隙锁,同时减少锁粒度和持有时间**。
transaction_isolation = 'READ-COMMITTED' 可禁用间隙锁(除外键和唯一检查外),大幅降低插入意向锁冲突概率,但需确认业务能接受幻读通过 InnoDB 状态诊断:
SELECT * FROM information_schema.INNODB_TRX 看当前运行事务SELECT * FROM information_schema.INNODB_LOCK_WAITS 看锁等待链SELECT * FROM information_schema.INNODB_LOCKS(MySQL 5.7+ 已废弃,8.0 用 performance_schema.data_locks)识别锁类型,插入意向锁显示为 INSERT_INTENTION
配合慢日志和应用层埋点,可定位具体哪条 INSERT 被阻塞、等在哪个间隙。