MySQL 数据库 MVCC 与锁如何联手解决脏读、不可重复读、幻读

MySQL 数据库 MVCC 与锁如何联手解决脏读、不可重复读、幻读

本篇我用 「现象 → 根因 → MVCC 是否能解决 → 需要什么锁」 的方式,把

👉 脏读 / 不可重复读 / 幻读MVCC / 锁机制 一一对上号。

前置说明:

  1. 什么是MVCC?
    参考:《MySQL 数据库 MVCC 机制
  2. 什么是脏读、不可重复读、幻读,及隔离级别?
    参考:《MySQL 数据库 隔离级别 详解
  3. 什么是间隙锁?
    参考:《InnoDB Gap Lock 避坑指南:为什么查不到数据也会锁表?
  4. 什么是 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

相关推荐
考虑考虑2 小时前
数据库中的EXISTS
运维·数据库·后端
Wang's Blog2 小时前
Java框架快速入门: Spring Security+OAuth2之数据库和实体类的RBAC改造
java·数据库·spring
梦想平凡3 小时前
百游棋牌源代码开发搭建教程(十):隔离部署、备份恢复与双端验收
java·前端·javascript·数据库·源代码管理
xcLeigh3 小时前
让大模型长出手脚,自己写SQL查数据库(Function Calling初探)
数据库·人工智能·sql·时序数据库·timechoai
yume_sibai4 小时前
06-Rust Web 开发实战(Axum 框架 + 数据库 + JWT 认证 + 中间件 + 部署)
前端·数据库·rust
AugustRed5 小时前
Neo4j 图数据库原理 + 应用场景简单介绍
数据库·neo4j
Gl�ria6 小时前
Redis 高可用架构对比
数据库·redis
IpdataCloud6 小时前
高可用的IP数据接口平台有哪些?从可用性、P99延迟到离线部署的评估框架(含代码)
数据库·tcp/ip·ip
呆萌很6 小时前
MySQL 数据库和表的管理操作(命令行)
数据库·mysql
毕业设计7037 小时前
(免费领源码)基于Python的博物馆研学活动管理系统的设计与实现22724- java、PHP、python、C#、小程序、大数据、单片机、网络工程等)
python·mysql·随机森林·pycharm·django·flask·推荐算法