MySQL 数据库 MVCC 机制

MySQL 数据库 MVCC 机制

    • 一句话定义(面试版)
    • [一、MVCC 解决了什么问题?](#一、MVCC 解决了什么问题?)
      • [有了 MVCC 之后](#有了 MVCC 之后)
    • [二、MVCC 的核心组成(3 个必考点)](#二、MVCC 的核心组成(3 个必考点))
      • [1️⃣ 隐藏字段(每一行都有)](#1️⃣ 隐藏字段(每一行都有))
      • [2️⃣ Undo Log(版本链)](#2️⃣ Undo Log(版本链))
      • [3️⃣ Read View(一致性视图)](#3️⃣ Read View(一致性视图))
    • [三、MVCC 是如何"读数据"的?](#三、MVCC 是如何“读数据”的?)
    • [四、快照读 vs 当前读(理解 MVCC 的关键)](#四、快照读 vs 当前读(理解 MVCC 的关键))
      • [1️⃣ 快照读(Snapshot Read)](#1️⃣ 快照读(Snapshot Read))
      • [2️⃣ 当前读(Current Read)](#2️⃣ 当前读(Current Read))
    • [五、RC vs RR 中 MVCC 的不同](#五、RC vs RR 中 MVCC 的不同)
    • [六、MVCC 不能解决什么?](#六、MVCC 不能解决什么?)
    • 七、一个完整例子(一步看懂)
      • 初始数据
      • [事务 A(RR)](#事务 A(RR))
      • [事务 B](#事务 B)
      • [事务 A 再读](#事务 A 再读)
    • [八、MVCC 的优缺点总结](#八、MVCC 的优缺点总结)
      • [✅ 优点](#✅ 优点)
      • [❌ 代价](#❌ 代价)
    • 九、一句话总结

在 MySQL(准确说是 InnoDB 存储引擎) 中,MVCC(Multi-Version Concurrency Control,多版本并发控制) 是一种 在不加锁或少加锁的情况下,实现高并发读写并保证事务隔离性 的机制。


一句话定义(面试版)

MVCC 是 InnoDB 通过保存数据的多个版本,让读操作读取历史版本,从而避免读写冲突、提升并发性能的一种机制。


一、MVCC 解决了什么问题?

在没有 MVCC 的情况下:

  • 读要加锁
  • 写要加锁
  • 读写互相阻塞

👉 并发性能非常差


有了 MVCC 之后

操作 是否阻塞
读 ↔ 读 不阻塞
读 ↔ 写 不阻塞
写 ↔ 写 阻塞

👉 读写并发能力大幅提升


二、MVCC 的核心组成(3 个必考点)

1️⃣ 隐藏字段(每一行都有)

InnoDB 每一行都有两个隐藏字段:

字段 作用
trx_id 最近一次修改该行的事务 ID
roll_pointer 指向 undo log 中旧版本的指针

2️⃣ Undo Log(版本链)

每次 UPDATE / DELETE:

  • 原数据不会被立即覆盖

  • 旧版本写入 undo log

  • 多个版本形成一条 版本链

    当前行 → v3 → v2 → v1(undo log)


3️⃣ Read View(一致性视图)

Read View 决定:

当前事务能"看到"哪个版本的数据

它包含:

  • m_ids:当前活跃事务 ID 列表
  • min_trx_id:最小活跃事务 ID
  • max_trx_id:下一个将分配的事务 ID
  • creator_trx_id:创建者事务 ID

Read View 更多介绍参考《MySQL 数据库 Read View 详解》


三、MVCC 是如何"读数据"的?

可见性规则(核心)

当事务读取一行时:

1️⃣ 拿到该行的 trx_id

2️⃣ 与 Read View 比较

判断规则简化为:

条件 是否可见
trx_id < min_trx_id ✅ 已提交
trx_id > max_trx_id ❌ 未来事务
trx_id 在 m_ids 中 ❌ 未提交
否则 ✅

如果不可见:

👉 通过 roll_pointer 找 旧版本


四、快照读 vs 当前读(理解 MVCC 的关键)

1️⃣ 快照读(Snapshot Read)

sql 复制代码
SELECT * FROM user WHERE id = 1;
  • 走 MVCC
  • 读历史版本
  • 不加锁

2️⃣ 当前读(Current Read)

sql 复制代码
SELECT * FROM user WHERE id = 1 FOR UPDATE;
UPDATE user SET name='A' WHERE id = 1;
  • 读最新版本
  • 不走 MVCC
  • 一定加锁

五、RC vs RR 中 MVCC 的不同

项目 RC RR
Read View 每条 SELECT 一个 事务级
是否可重复读 ❌ ✅
普通 SELECT 快照读 快照读
幻读处理 Read View 锁 + MVCC

📌 注意:

MVCC 只对普通 SELECT 生效


六、MVCC 不能解决什么?

❌ 写写冲突

❌ 当前读的幻读

❌ SERIALIZABLE 下的并发问题

👉 所以 InnoDB 仍然需要:

  • 行锁
  • Gap Lock
  • Next-Key Lock

七、一个完整例子(一步看懂)

初始数据

复制代码
id=1, balance=100

事务 A(RR)

sql 复制代码
START TRANSACTION;
SELECT balance FROM account WHERE id=1;

👉 读到 100


事务 B

sql 复制代码
UPDATE account SET balance=200 WHERE id=1;
COMMIT;

事务 A 再读

sql 复制代码
SELECT balance FROM account WHERE id=1;
  • RR:仍读 100
  • RC:读 200

📌 都没加锁


八、MVCC 的优缺点总结

✅ 优点

  • 高并发
  • 减少锁
  • 读写不互斥

❌ 代价

  • 占用 undo log 空间
  • 长事务影响性能
  • 实现复杂

九、一句话总结

MVCC 是 InnoDB 通过 undo log + Read View,让普通 SELECT 在不加锁的情况下读取一致性数据的核心机制。

相关推荐
Xxtaoaooo2 分钟前
NocoDB在线表格数据库:fnOS部署、MySQL可视化与远程协作实操
数据库·mysql·docker·cpolar·nocodb
张继雁7 分钟前
30~50MPa数控高压清洗:前端分级过滤逻辑,抑制硬质磨粒对喷嘴冲蚀
大数据·数据库·人工智能·机器学习·创业创新
言乐610 分钟前
PythonLOLM自动生成复盘报告模型
开发语言·前端·数据库·人工智能·python
倔强的石头_14 分钟前
从 KStudio 到 KSQL Developer:国产数据库的 SQL 编辑器,已经卷到这个程度了
数据库
JavaEdge.26 分钟前
设定索引方法和检索设置
数据库
小蒜学长30 分钟前
基于Vue.js + Spring Boot的酒店客房预订系统设计与实现(代码+数据库+LW)
java·数据库·spring boot·后端·酒店客房预订系统
墨者阳30 分钟前
KingbaseES V9R2C16 深度实测:64位事务ID、内存防护、集群备份与坏块修复四大能力全解析
数据库
事圆则缓36 分钟前
聊天与引用回复的 SQL 怎么设计
数据库·sql
APItesterCris37 分钟前
告别反复手工查价:用 Open‑Claw 搭建商品监控与数据分析小工具
大数据·数据库·数据仓库·自动化
来福猿41 分钟前
分布式锁 Redis 实现源码分析:SETNX、过期时间与可重入设计
数据库·redis·分布式