
MVCCMulti-Version Concurrency Control多版本并发控制是数据库解决读写并发冲突的一种机制。它的核心思想不是加读锁而是给一行数据保存多个版本让读操作读历史版本写操作写新版本从而实现“读不阻塞写写不阻塞读”。为什么需要 MVCC假设账户表idbalance1100场景事务ABEGIN; UPDATE account SET balance 200 WHERE id 1;此时还没提交。事务BSELECT balance FROM account WHERE id 1;怎么办如果没有 MVCC方案1加锁事务A写锁 ↓ 事务B必须等待并发能力差。方案2脏读事务B直接读到200如果A回滚ROLLBACK;数据又变成100。B读到了不存在的数据。MVCC的方案事务A写新版本 事务B读旧版本互不影响。InnoDB 如何实现 MVCC核心依赖三个东西隐藏字段 Undo Log Read View1. 隐藏字段InnoDB 每行数据都有两个重要隐藏列trx_id roll_pointer例如idnametrx_id1Tom100trx_id记录最后修改该行的事务ID例如事务100修改 trx_id 100roll_pointer指向 Undo Log。当前记录 ↓ Undo Log ↓ Undo Log形成版本链。2. Undo Log假设初始数据Tom事务101UPDATE user SET nameJack WHERE id1;变成Jack同时保存旧版本Undo Log - Tom事务102UPDATE user SET nameLucy WHERE id1;变成LucyUndo链Lucy ↓ Jack ↓ Tom这就是版本链。3. Read View这是 MVCC 最核心的东西。Read View 可以理解为事务启动时看到的世界快照记录哪些事务已经提交 哪些事务还没提交例如当前事务ID100 101 102 103事务104开始查询SELECT * FROM user;生成Read View记录当前活跃事务101 102可见性判断假设当前记录trx_id 100因为100 104已提交。可见。如果trx_id 102发现102在活跃事务列表说明未提交。不可见。继续沿 Undo Log 找旧版本。最终找到trx_id100可见。返回。整个过程例如事务ABEGIN; UPDATE user SET nameLucy;未提交。事务BSELECT name FROM user;看到当前版本 Lucy trx_id101发现101未提交不可见。沿着 Undo LogLucy ↓ Jack ↓ Tom找到Tom trx_id100可见。返回TomMVCC解决了什么问题读不阻塞写事务AUPDATE事务BSELECT不需要等待。写不阻塞读读历史版本即可。大幅提高并发传统锁机制读锁 写锁 互斥大量等待。MVCC写当前版本 读历史版本并发能力提升很多。MVCC在哪些隔离级别生效Read Uncommitted不使用MVCC直接读最新数据。可能脏读。Read Committed使用MVCC。每次查询生成新的 Read View。查询1 ReadView1 查询2 ReadView2所以可能不可重复读。Repeatable ReadMySQL默认使用MVCC。事务第一次查询生成 Read View。后续一直使用。事务开始 ReadView固定 查询1 查询2 查询3因此实现可重复读。Serializable直接加锁。SELECT 加共享锁基本不依赖MVCC。面试总结如果面试官问什么是 MVCC可以回答MVCC多版本并发控制是 InnoDB 实现高并发读写的重要机制其核心思想是通过保存数据的多个历史版本让读操作读取符合事务快照的版本而不是直接加锁等待。InnoDB 的 MVCC 主要依赖隐藏字段trx_id和roll_pointerUndo Log 构成的版本链Read View 进行可见性判断查询时根据 Read View 判断当前版本是否可见不可见则沿 Undo Log 回溯历史版本直到找到可见版本。因此 MVCC 实现了读不阻塞写 写不阻塞读 提高并发性能这也是 MySQL InnoDB 在Read Committed和Repeatable Read隔离级别下实现一致性读的核心原理。