MySQL 数据库 MVCC 与锁如何联手解决脏读、不可重复读、幻读
- 先给你结论
- [一、脏读(Dirty Read)](#一、脏读(Dirty Read))
- [二、不可重复读(Non-Repeatable Read)](#二、不可重复读(Non-Repeatable Read))
- [三、幻读(Phantom Read)](#三、幻读(Phantom Read))
- 四、把三者放到一张"机制对照表"
- [五、InnoDB 的终极设计思想](#五、InnoDB 的终极设计思想)
- 六、一个终极判断方法
- 七、总结
本篇我用 「现象 → 根因 → MVCC 是否能解决 → 需要什么锁」 的方式,把
👉 脏读 / 不可重复读 / 幻读 和 MVCC / 锁机制 一一对上号。
前置说明:
- 什么是MVCC?
参考:《MySQL 数据库 MVCC 机制》- 什么是脏读、不可重复读、幻读,及隔离级别?
参考:《MySQL 数据库 隔离级别 详解》- 什么是间隙锁?
参考:《InnoDB Gap Lock 避坑指南:为什么查不到数据也会锁表?》- 什么是 Next-Key Lock ?
参考:《3 分钟搞懂 Next-Key Lock:原理、触发场景》
先给你结论
并发现象 能否靠 MVCC 解决 还需不需要锁
---------------------------------------------------
脏读 ✅(最容易) ❌
不可重复读 ✅(RC / RR) ❌
幻读 ❌(仅 MVCC 不够) ✅(Next-Key Lock)
📌 关键记忆点:
MVCC 解决 "读旧数据" 的问题;
锁解决 "别人还能不能写" 的问题。
一、脏读(Dirty Read)
现象回顾
读到了 未提交 的数据
根因
- 没有版本隔离
- 直接读当前内存中的最新值
MVCC 怎么解决?
✅ 完全可以
-
Read View 只允许读:
- 已提交事务
- 自己的事务
text
未提交事务 ∈ m_ids → 不可见
👉 自然不会脏读
需要锁吗?
❌ 不需要
- 读历史版本即可
- 写回滚也不影响读
对应隔离级别
| 隔离级别 | 是否可能脏读 |
|---|---|
| RU | ❌ |
| RC / RR | ✅(MVCC) |
二、不可重复读(Non-Repeatable Read)
现象回顾
同一行,两次读结果不同
根因
- 两次 SELECT 使用了 不同的可见性规则
- 世界观"变了"
MVCC 怎么解决?
✅ 可以
RC
- 每条 SELECT 新 Read View
- 所以 仍可能不可重复读
RR
- 事务级 Read View
- 多次 SELECT 看到的是同一个版本
👉 可重复读成立
需要锁吗?
❌ 不需要
- 不要求别人不能改
- 只是"我想看到一致视图"
对应隔离级别
| 隔离级别 | 不可重复读 |
|---|---|
| RC | ❌ |
| RR | ✅ |
三、幻读(Phantom Read)
现象回顾
同一条件,两次读到 不同行数
根因(重点)
- 插入了新行
- 新行在第一次 SELECT 时根本不存在
- MVCC 只能决定"看哪个版本",无法阻止新行出现
MVCC 能解决吗?
❌ 只能解决一半
快照读(普通 SELECT)
- 第二次 SELECT
- 仍使用原 Read View
- 看不到新插入行
👉 "看不到幻影"
当前读(FOR UPDATE / UPDATE)
- 必须读最新数据
- 不走 MVCC
- 新行真实存在
👉 幻读仍可能发生
那怎么办?
✅ 必须靠锁
Next-Key Lock = 行锁 + 间隙锁
锁住"未来可能插入的位置"
→ 插不进
→ 不会幻读
对应隔离级别
| 隔离级别 | 幻读 |
|---|---|
| RC | ❌(逻辑可能) |
| RR(InnoDB) | ✅(锁 + MVCC) |
四、把三者放到一张"机制对照表"
| 并发现象 | 发生在 | MVCC 是否足够 | 锁是否必须 |
|---|---|---|---|
| 脏读 | RU | ✅ | ❌ |
| 不可重复读 | RC | RR 下 ✅ | ❌ |
| 幻读 | RC / 标准 RR | ❌ | ✅ |
五、InnoDB 的终极设计思想
能用 MVCC 解决的,一律不加锁;
MVCC 解决不了的,才用锁;
锁只在"当前读"时才出现。
六、一个终极判断方法
读旧数据 → MVCC;
不让别人改 → 锁;
不让别人插 → Gap / Next-Key Lock。
七、总结
脏读和不可重复读是"看不看历史版本"的问题,
幻读是"新数据能不能出现"的问题,
前者靠 MVCC,后者必须靠锁。
若有转载🧪请标明出处:https://blog.csdn.net/CharlesYuangc/article/details/156310464