Skip to content

Mvcc实现原理

MVCC(Multi-Version Concurrency Control,多版本并发控制) 是一种数据库并发控制机制,通过为数据维护多个版本,避免读写冲突,实现事务隔离。它的核心原理是:每个事务看到的数据是一个一致性快照,写操作创建新版本而非直接修改原数据,依赖版本标识(如时间戳或事务 ID)和版本管理(如快照或回滚段)实现。

关键事实

  1. 基本原理
    • 数据记录保存多个版本,每个版本标记创建时间或事务 ID。
    • 读事务访问符合其隔离级别的数据版本,写事务生成新版本。
    • 旧版本在不需要时被清理(垃圾回收)。
  2. 核心组件
    • 版本标识:如事务 ID(TID)或时间戳,区分不同版本。
    • 快照:事务开始时记录可见数据版本。
    • 元数据:记录版本的创建和删除信息(如创建事务 ID、删除事务 ID)。
  3. 工作流程
    • 读操作:根据事务的开始时间或隔离级别,选择可见的版本。
    • 写操作:复制旧数据,创建新版本,标记新版本的事务 ID。
    • 提交/回滚:提交后新版本生效,回滚则丢弃新版本。
  4. 隔离级别支持
    • 读已提交:读取最新提交的版本。
    • 可重复读:读取事务开始时的快照版本。

示例(以 MySQL InnoDB 为例)

  • 表结构:每行数据有隐藏列:
    • DB_TRX_ID:创建该版本的事务 ID。
    • DB_ROLL_PTR:指向回滚段的指针(旧版本)。
  • 事务操作
    • 事务 T1(ID=100)更新 balance=50 为 60,创建新版本,旧版本存回滚段。
    • 事务 T2(ID=101)读取时:
      • 读已提交:看到 60(最新提交)。
      • 可重复读:看到 50(T2 开始时的快照)。
  • 快照:T2 开始时记录活跃事务列表,只读小于其 ID 的版本。 记录: 版本1: balance=50, DB_TRX_ID=90 版本2: balance=60, DB_TRX_ID=100, DB_ROLL_PTR -> 版本1

延伸与面试角度

  • 实现细节
    • 版本存储:InnoDB 用回滚段(undo log)保存旧版本。
    • 可见性判断:事务对比记录的 DB_TRX_ID 和活跃事务列表。
    • 垃圾回收:提交后,旧版本在无事务引用时清理。
  • 为什么高效?
    • 读不阻塞写:读旧版本,写创建新版本,无需锁等待。
    • 写不阻塞读:新版本对未提交事务不可见。
  • 与锁的对比
    • 锁(悲观控制):读写互斥,适合写多场景。
    • MVCC(乐观控制):读写分离,适合读多场景。
  • 实际应用
    • MySQL InnoDB:默认可重复读,MVCC 避免不可重复读。
    • PostgreSQL:每行存多版本,支持串行化。
  • 优缺点
    • 优点:高并发读写,隔离性强。
    • 缺点:空间开销大(存多版本),需垃圾回收。

总结

MVCC 通过多版本数据和快照实现隔离性,读事务访问历史版本,写事务创建新版本,依赖版本标识和回滚机制。MySQL InnoDB 用事务 ID 和回滚段实现,支持读已提交和可重复读。面试时,可结合 InnoDB 示例或与锁机制对比,展示深入理解。