Mvcc实现原理
MVCC(Multi-Version Concurrency Control,多版本并发控制) 是一种数据库并发控制机制,通过为数据维护多个版本,避免读写冲突,实现事务隔离。它的核心原理是:每个事务看到的数据是一个一致性快照,写操作创建新版本而非直接修改原数据,依赖版本标识(如时间戳或事务 ID)和版本管理(如快照或回滚段)实现。
关键事实
- 基本原理:
- 数据记录保存多个版本,每个版本标记创建时间或事务 ID。
- 读事务访问符合其隔离级别的数据版本,写事务生成新版本。
- 旧版本在不需要时被清理(垃圾回收)。
- 核心组件:
- 版本标识:如事务 ID(TID)或时间戳,区分不同版本。
- 快照:事务开始时记录可见数据版本。
- 元数据:记录版本的创建和删除信息(如创建事务 ID、删除事务 ID)。
- 工作流程:
- 读操作:根据事务的开始时间或隔离级别,选择可见的版本。
- 写操作:复制旧数据,创建新版本,标记新版本的事务 ID。
- 提交/回滚:提交后新版本生效,回滚则丢弃新版本。
- 隔离级别支持:
- 读已提交:读取最新提交的版本。
- 可重复读:读取事务开始时的快照版本。
示例(以 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 示例或与锁机制对比,展示深入理解。