插入意向锁 (Insert Intention Lock)
📋 概述
插入意向锁(Insert Intention Lock)是 MySQL InnoDB 引擎在 INSERT 操作时使用的一种特殊锁。它本质上是一种特殊的间隙锁,用于表明事务打算在某个间隙中插入记录。
核心特点
✅ 优点:
- 提高并发: 多个事务可以在不同位置并发插入
- 冲突检测: 快速检测插入冲突
- 自动管理: InnoDB 自动处理
- 死锁预防: 帮助检测和预防死锁
❌ 缺点:
- 理解复杂: 概念较抽象
- 可能死锁: 与间隙锁交互时可能死锁
- 仅 InnoDB: MySQL InnoDB 特有
适用场景
- INSERT 操作: 所有插入操作
- 并发插入: 多个事务同时插入
- 唯一索引检查: 检查唯一约束冲突
- 间隙锁共存: 与间隙锁的交互场景
🔧 工作原理
锁的本质
插入意向锁是一种特殊的间隙锁,但与普通间隙锁不同:
- 普通间隙锁: 阻止其他事务插入
- 插入意向锁: 表明"我打算在这里插入"
工作流程
sql
-- 假设表中有 id = 1, 5, 10 的记录
-- 间隙为: (1, 5), (5, 10)
-- 事务 A
INSERT INTO users VALUES (3, 'john');
-- 在间隙 (1, 5) 上加插入意向锁
-- 事务 B(同时)
INSERT INTO users VALUES (7, 'jane');
-- 在间隙 (5, 10) 上加插入意向锁
-- ✅ 不冲突,可以并发执行与间隙锁的交互
sql
-- 事务 A
BEGIN;
SELECT * FROM users WHERE id = 5 FOR UPDATE;
-- 锁定间隙 (1, 5) 和 (5, 10)(间隙锁)
-- 事务 B
INSERT INTO users VALUES (3, 'john');
-- ❌ 被阻塞!插入意向锁与间隙锁冲突💻 MySQL InnoDB 实现
查看插入意向锁
sql
-- 查看插入意向锁
SELECT
lock_id,
lock_trx_id,
lock_mode,
lock_type,
lock_table,
lock_index,
lock_data
FROM performance_schema.data_locks
WHERE lock_mode = 'X,GAP'; -- 插入意向锁显示为 X,GAP死锁示例
sql
-- 事务 A
BEGIN;
SELECT * FROM users WHERE id = 5 FOR UPDATE; -- 间隙锁 (1, 5) 和 (5, 10)
-- 事务 B
BEGIN;
SELECT * FROM users WHERE id = 10 FOR UPDATE; -- 间隙锁 (5, 10) 和 (10, +∞)
-- 事务 A
INSERT INTO users VALUES (7, 'john'); -- 尝试在 (5, 10) 插入,被事务 B 阻塞
-- 事务 B
INSERT INTO users VALUES (3, 'jane'); -- 尝试在 (1, 5) 插入,被事务 A 阻塞
-- 💥 死锁!InnoDB 会检测并终止其中一个事务🎯 最佳实践
✅ 推荐做法
1. 固定插入顺序
sql
-- ✅ 按主键顺序插入,减少死锁
INSERT INTO users VALUES (1, 'user1');
INSERT INTO users VALUES (2, 'user2');
INSERT INTO users VALUES (3, 'user3');2. 批量插入优化
sql
-- ✅ 批量插入,减少锁竞争
INSERT INTO users VALUES
(1, 'user1'), (2, 'user2'), (3, 'user3');❌ 避免陷阱
1. 避免随机插入导致死锁
sql
-- ❌ 危险:多个事务随机插入同一范围
-- 事务 A: INSERT INTO users VALUES (3, ...);
-- 事务 B: INSERT INTO users VALUES (4, ...);
-- 如果有间隙锁,可能死锁🚨 常见问题
Q1: 插入意向锁会阻塞其他插入吗?
答: 不会。多个插入意向锁互相兼容,只在与间隙锁冲突时才阻塞。
Q2: 如何避免插入意向锁导致的死锁?
答:
- 按顺序插入
- 批量插入
- 缩短事务时间
- 设置超时
📚 相关资源
内部链接
外部资源
最后更新: 2026-04-12
维护状态: ✅ 完整