当前位置: 首页 > news >正文

InnoDB 存储引擎对 MVCC 的实现详解

MVCC(Multi-Version Concurrency Control,多版本并发控制)是 InnoDB 实现事务隔离级别和提高并发性能的关键机制。它允许数据库在 不加锁的情况下进行一致性读,提高读写并发性能。


一、什么是 MVCC?

MVCC 的核心思想:

  • 每条记录(行)保留多个版本(通过隐藏列和 Undo Log)。
  • 事务读取数据时,读取满足其 一致性视图(Read View) 的版本,而不是最新版本。
  • 这样可以避免大部分读操作加锁,减少阻塞。

目标

  • 实现 快照读(非锁定读),提高并发性能。
  • 保证事务隔离级别,特别是 READ COMMITTEDREPEATABLE READ

二、InnoDB 实现 MVCC 的核心机制

InnoDB 的 MVCC 主要通过以下机制实现:

  1. 隐藏列
  2. Undo Log(回滚日志)
  3. Read View(读视图)

1. 隐藏列

InnoDB 每行记录都有两个隐藏列(实际上是三列):

  • DB_TRX_ID:最后修改该行的事务 ID。
  • DB_ROLL_PTR:回滚指针,指向 Undo Log,记录旧版本。
  • DB_ROW_ID(可选):自增 ID(如果没有显式主键)。

2. Undo Log(回滚日志)

Undo Log 保存了 行数据的历史版本,用于:

  • MVCC 版本链(保证一致性读)。
  • 事务回滚

版本链结构

  • 每次 UPDATE 或 DELETE,都会把 旧版本 写入 Undo Log,并用 回滚指针(DB_ROLL_PTR) 链接。
  • 这样就形成一条 历史版本链

示意图:


最新版本(当前行) → Undo Log V1 → Undo Log V2 → ...

3. Read View(读视图)

Read View 是事务执行一致性读时创建的视图,决定事务可以“看到”哪些版本。

包含以下关键字段:

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

版本可见性规则

  • 如果版本的 DB_TRX_ID 小于 min_trx_id → 可见(已提交)。
  • 如果版本的 DB_TRX_ID 大于 max_trx_id → 不可见(未开始)。
  • 如果版本的 DB_TRX_ID 在活跃事务列表中 → 不可见(未提交)。
  • 否则,可见。

三、MVCC 的读取类型

1. 快照读(Snapshot Read)

  • 普通 SELECT 语句(无 FOR UPDATE)。
  • 不加锁,通过 MVCC 实现一致性读。
  • 读取 事务开始时的快照

2. 当前读(Current Read)

  • 加锁读取:SELECT ... FOR UPDATE / LOCK IN SHARE MODE / UPDATE / DELETE
  • 读取最新版本,并对记录加锁。

四、MVCC 与事务隔离级别的关系

READ COMMITTED(读已提交)

  • 每次执行 SELECT 都生成新的 Read View。
  • 可能出现 不可重复读

REPEATABLE READ(可重复读)

  • 事务启动时生成 Read View,整个事务期间复用。
  • 解决不可重复读问题。
  • InnoDB 默认隔离级别,结合 Next-Key Lock 可避免幻读。

五、MVCC 的工作流程示例

假设事务隔离级别为 REPEATABLE READ

事务 A
START TRANSACTION;
SELECT * FROM account WHERE id = 1; -- 创建 Read View
事务 B
START TRANSACTION;
UPDATE account SET balance = 200 WHERE id = 1; -- 修改 DB_TRX_ID,写入 Undo Log
COMMIT;
事务 A 再次读取
SELECT * FROM account WHERE id = 1; -- 仍然读取旧版本(通过 Undo Log)

结果

  • A 看到的是事务开始时的版本。
  • B 修改的新值对 A 不可见。

六、MVCC 版本链结构图

最新记录:balance = 200, DB_TRX_ID = 30, DB_ROLL_PTR -> V1
V1:balance = 100, DB_TRX_ID = 20, DB_ROLL_PTR -> NULL
  • 事务 A 的 Read View:活跃事务 ID 列表 = [30],min_trx_id = 20,max_trx_id = 31。

  • A 读取时发现:

    • 最新版本(trx_id=30)在活跃事务列表中 → 不可见。
    • 找 Undo Log V1(trx_id=20)→ 可见。

七、MVCC 的优缺点

优点

  • 读操作不加锁,提高并发性能。
  • 减少死锁风险。

缺点

  • 需要维护 Undo Log,占用空间。
  • 长事务可能导致 Undo Log 膨胀,影响性能。

八、面试高频问答

Q1:InnoDB 的 MVCC 是如何实现的?

  • 通过 隐藏列(DB_TRX_ID、DB_ROLL_PTR)+ Undo Log + Read View
  • 使用版本链实现多版本控制。

Q2:快照读和当前读的区别?

  • 快照读:普通 SELECT,使用 MVCC,不加锁。
  • 当前读:UPDATE、DELETE、SELECT … FOR UPDATE,读取最新版本并加锁。

Q3:不同隔离级别下 Read View 什么时候创建?

  • READ COMMITTED:每次 SELECT 都新建。
  • REPEATABLE READ:事务第一次 SELECT 时创建并复用。

Q4:MVCC 如何解决不可重复读?

  • 在 REPEATABLE READ 下,事务使用同一个 Read View,始终看到一致的版本。

Q5:幻读能通过 MVCC 解决吗?

  • 不能完全解决,需要结合 Next-Key Lock

九、总结

组件作用
隐藏列存储事务 ID 和 Undo Log 指针
Undo Log保存旧版本数据,用于回滚和一致性读
Read View定义事务可见版本,保证隔离性

关键点

  • MVCC 提供 高性能一致性读,减少锁竞争。
  • 通过版本链 + Read View 实现事务隔离。
  • Undo Log 膨胀问题需要控制长事务。
http://www.dtcms.com/a/317622.html

相关文章:

  • [Linux]学习笔记系列 -- [arm][debug]
  • QtMqtt库的编译以及安装
  • 导入Excel打印
  • Excel将整列值转换为字符串
  • 面向流程和产品的安全档案论证方法
  • C语言access函数详解:文件访问权限检查的利器
  • 在WPS或Word中,实现换行不换段落
  • 浙大高飞团队新作:提出层级式探索框架,让「地空双模」机器人自主决策“飞”或“走”
  • 深入理解 C++ 中的stdpriority_queue:从原理到实战的高效优先级管理
  • 并发编程常见问题排查与解决:从死锁到线程竞争的实战指南
  • #3:Maven进阶与私服搭建
  • 自然语言处理基础—(1)
  • MyBatis核心配置深度解析:从XML到映射的完整技术指南
  • UI测试平台TestComplete的AI视觉引擎技术解析
  • 脑洞大开——AI流程图如何改变思维?
  • dify之智能旅游系统应用
  • 旅游|基于Springboot的旅游管理系统设计与实现(源码+数据库+文档)
  • Spring Boot + Tesseract异步处理框架深度解析,OCR发票识别流水线
  • 插槽的使用
  • 【AI智能编程】Trae-IDE工具学习
  • nginx代理出https,request.getRequestURL()得到http问题解决
  • SQL120 贷款情况
  • OpenCV校准双目相机并测量距离
  • AsyncAppende异步 + 有界队列 + 线程池实现高性能日志系统
  • 【Axure高保真原型】批量添加和删除图片
  • 目录遍历漏洞学习
  • 概率/期望 DP Jon and Orbs
  • 低代码系统的技术深度:超越“可视化操作”的架构与实现挑战
  • 基于51单片机的温控风扇Protues仿真设计
  • 【FAQ】Script导出SharePoint 目录文件列表并统计大小