InnoDB 在删除插入记录过程中锁的“继承机制”了解吗?
1 个回答
不要和差点意思的人周旋。蔡琳## 问题简化场景: 假设 B+ 树主键顺序如下: ``` Record IDs: 1 2 3 ``` 现在: 1. **事务 A 插入了 `id = 2`,尚未提交** * 这时候是一个 **隐式 Record Lock**,未正式写入 `innodb_locks` 表 2. 事务 B 尝试操作 `id = 2`: * 会触发 **显式构造 Record Lock**,等待事务 A 3. 后来 **`id = 2` 被事务 A 删除或回滚** * 这时候 `id = 2` 那条记录连同锁也应该被移除 ## ❗问题来了: > 原本等待 `id = 2` 的锁,不能随着记录的删除被“无声抹去”,否则其它事务(比如事务 C)马上可以插入 `id = 2`,破坏了隔离性。 所以—— ## InnoDB 的真实做法是: > **将 `id = 2` 上的 Record Lock 转化为对 `(1, 3)` 间隙的 Gap Lock,并挂在 `id = 3` 上**,以此维持锁语义。 这就叫做: > **锁继承(Lock Inherit)+ 锁迁移(Lock Migrate)** ## 🔍 技术解释: * 原来持有 `id = 2` 上的 **Record Lock** * 删除记录后,该锁对象不能直接释放(否则等待它的事务逻辑会出错) * InnoDB 会将其作为 **Gap Lock** 转移到下一个记录(`id = 3`)上 * 用于表示 `(1, 3)` 间隙暂时不可插入(还在等待某个逻辑上的锁释放) ## 这个过程不是“插入产生了间隙锁”,而是: > 插入 → 被访问 → 构建了显式 Record Lock → 后续删除 → **触发锁继承逻辑 → 转成 Gap Lock** 所以: | 过程 | 是否加间隙锁 | | ----------- | ---------------------------------- | | `INSERT` 本身 | ❌ 不会加 Gap Lock | | 插入后被等待 | ✅ 构造 Record Lock | | 插入记录被删除 | ✅ 转化为 Gap Lock,锁结构挂靠后继记录(如 id = 3) | ## 图示(你说得对): ``` 初始记录: 1 2 3 INSERT 2 → 隐式锁 事务 B 访问 2 → 2 上构建 Record Lock DELETE 2 → Record Lock 迁移为 Gap Lock → 挂在 3 上,锁定 (1,3) ``` ## 总结一句话: > 插入本身不会产生间隙锁;但如果被其他事务等待、又被删除,InnoDB 会把原本的行锁“转化为 Gap Lock”继承给后继记录,以保持锁语义,防止幻读或破坏事务隔离。编辑于 2025-07-31 06:03 •IP属地 北京举报评论收藏
公众号进入网站体验更佳

