MVCC的底层实现原理是什么?

MVCC(多版本并发控制)的底层实现核心在于数据版本链可见性判断规则(Read View) ,InnoDB 通过 Undo LogRead View 协同工作实现这一机制。以下是详细原理:


一、核心组件与流程

1. 数据版本链 (Undo Log)
  • 作用:存储数据行的历史版本,构成版本链。
  • 结构
    • 每行数据包含两个隐藏字段:
      • DB_TRX_ID (6字节):最近修改该行的事务ID。
      • DB_ROLL_PTR (7字节):指向该行上一个历史版本在 Undo Log 中的指针。
    • 每次更新数据时:
      1. 生成新的 Undo Log 记录旧数据。
      2. 新行写入当前数据,DB_TRX_ID 设为当前事务ID。
      3. DB_ROLL_PTR 指向刚生成的 Undo Log 记录。
  • 版本链形成 :通过 DB_ROLL_PTR 指针,将同一数据行的所有历史版本串联成一个链表(按修改时间倒序),链头是最新版本。
2. 快照视图 (Read View)
  • 作用 :事务执行快照读 (如 SELECT)时创建,用于判断版本链中哪个版本对该事务可见。
  • 关键属性
    • m_ids:生成 Read View 时,系统中所有活跃(未提交)事务ID的集合。
    • min_trx_idm_ids 中的最小事务ID。
    • max_trx_id:生成 Read View 时,系统应分配给下一个新事务的ID(即当前最大事务ID+1)。
    • creator_trx_id:创建该 Read View 的事务ID(对于只读事务,可能为0)。
  • 可见性判断规则 :遍历版本链时,对每个版本的 DB_TRX_ID (记为 trx_idtrx\_idtrx_id) 应用以下规则:
    1. 可访问 :如果 trx_id<min_trx_idtrx\_id < min\_trx\_idtrx_id<min_trx_id,说明该版本在 Read View 创建前已提交,可见
    2. 不可访问 :如果 trx_id≥max_trx_idtrx\_id \geq max\_trx\_idtrx_id≥max_trx_id,说明该版本在 Read View 创建后才生成,不可见
    3. 活跃事务 :如果 min_trx_id≤trx_id<max_trx_idmin\_trx\_id \leq trx\_id < max\_trx\_idmin_trx_id≤trx_id<max_trx_id:
      • 若 trx_id∈m_idstrx\_id \in m\_idstrx_id∈m_ids,说明该版本由未提交的事务修改,不可见
      • 若 trx_id∉m_idstrx\_id \notin m\_idstrx_id∈/m_ids,说明该版本在 Read View 创建时已提交,可见
    4. 自身修改 :如果 trx_id=creator_trx_idtrx\_id = creator\_trx\_idtrx_id=creator_trx_id,说明该版本是当前事务自己修改的,可见
  • 遍历过程 :从最新版本开始,依次检查 DB_TRX_ID,直到找到第一个满足可见性条件的版本。

二、不同隔离级别的实现差异

1. 读已提交 (READ COMMITTED)
  • Read View 生成时机每次执行快照读时 都会生成一个新的 Read View
  • 效果 :每次读都能看到最新已提交的数据。其他事务只要提交,当前事务的下一次读就能看到。
2. 可重复读 (REPEATABLE READ - InnoDB默认)
  • Read View 生成时机 :在事务中第一次执行快照读时 生成,后续所有快照读都复用同一个 Read View
  • 效果 :在整个事务期间,看到的数据版本是一致的(第一次读时的快照),不受其他已提交事务影响,实现了可重复读 。同时,通过 Next-Key Lock 防止幻读。

三、关键概念区分

  1. 快照读 (Snapshot Read)
    • 普通 SELECT 语句(不加 FOR UPDATE/SHARE)。
    • 基于 MVCC 机制读取历史版本。
    • 无锁(或仅加极轻量级的锁,如检查 schema 版本)。
  2. 当前读 (Current Read)
    • SELECT ... FOR UPDATE/SHARE, UPDATE, DELETE, INSERT
    • 总是读取最新已提交的数据版本。
    • 需要加锁(记录锁、间隙锁、Next-Key Lock)以保证数据一致性和防止冲突。

四、垃圾回收 (Purge)

  • 问题 :历史版本 (Undo Log) 不会永久保留。
  • 机制 :InnoDB 后台的 Purge 线程负责清理不再需要的旧版本数据。
  • 清理条件 :当系统中没有 任何 Read View 需要访问某个旧版本时,该版本才能被安全删除。

总结 :MVCC 的底层实现 = Undo Log 构建版本链 + Read View 判断可见性 。通过控制 Read View 的生成时机,实现了不同隔离级别的语义。快照读依赖 MVCC 提供无锁并发读,当前读则依赖锁机制保证数据强一致性。


相关推荐
guodingdingh4 小时前
软件开发工作问题总结0718
java·开发语言·数据库
咖啡八杯5 小时前
GoF设计模式——解释器模式
java·后端·spring·设计模式
GuWenyue6 小时前
Cursor黑盒拆解!1套LangChain.js手写Mini编程Agent,自动生成React项目,效率提升60%
前端·数据库·人工智能
优橙教育6 小时前
5G网优培训 vs Java开发:转行选哪个?
java·开发语言·5g
掘金码甲哥6 小时前
这块终端神器, 必须吹爆!
后端
糖果店的幽灵6 小时前
【DeepAgents 从入门到精通】Context Management 上下文管理
java·人工智能·后端·spring·中间件·langgraph·deepagents
Csvn7 小时前
📊 SQL 入门 Day 8:集合操作 — 用 SQL 做数学里的"并交差"
后端·sql
腻害兔7 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:字典、短信、邮件、通知——后台系统的“基础设施四件套“!
java·前端·vue.js·产品经理·ai编程
Miao121318 小时前
某海外住宿平台如何在大规模场景下实现指标一致性:Minerva 指标平台实践
大数据·数据库·人工智能
CodexDave8 小时前
MySQL事务隔离级别与MVCC机制解析
前端·数据库·mysql·nginx·性能优化·负载均衡