什么是MVCC
2026/6/21 1:55:55 网站建设 项目流程

MVCC(Multi-Version Concurrency Control,多版本并发控制)是数据库解决读写并发冲突的一种机制。

它的核心思想不是加读锁,而是:

给一行数据保存多个版本,让读操作读历史版本,写操作写新版本,从而实现“读不阻塞写,写不阻塞读”。


为什么需要 MVCC

假设账户表:

idbalance
1100

场景

事务A:

BEGIN; UPDATE account SET balance = 200 WHERE id = 1;

此时还没提交。


事务B:

SELECT 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 View

1. 隐藏字段

InnoDB 每行数据都有两个重要隐藏列:

trx_id roll_pointer

例如:

idnametrx_id
1Tom100

trx_id

记录:

最后修改该行的事务ID

例如:

事务100修改 trx_id =100

roll_pointer

指向 Undo Log。

当前记录 ↓ Undo Log ↓ Undo Log

形成版本链。


2. Undo Log

假设:

初始数据:

Tom

事务101:

UPDATE user SET name='Jack' WHERE id=1;

变成:

Jack

同时保存旧版本:

Undo Log -> Tom

事务102:

UPDATE user SET name='Lucy' WHERE id=1;

变成:

Lucy

Undo链:

Lucy ↓ Jack ↓ Tom

这就是版本链。


3. Read View

这是 MVCC 最核心的东西。

Read View 可以理解为:

事务启动时看到的世界快照

记录:

哪些事务已经提交 哪些事务还没提交

例如:

当前事务ID:

100 101 102 103

事务104开始查询:

SELECT * FROM user;

生成:

Read View

记录当前活跃事务:

101 102

可见性判断

假设当前记录:

trx_id = 100

因为:

100 < 104

已提交。

可见。


如果:

trx_id = 102

发现:

102在活跃事务列表

说明未提交。

不可见。

继续沿 Undo Log 找旧版本。


最终找到:

trx_id=100

可见。

返回。


整个过程

例如:

事务A:

BEGIN; UPDATE user SET name='Lucy';

未提交。


事务B:

SELECT name FROM user;

看到:

当前版本: Lucy trx_id=101

发现:

101未提交

不可见。


沿着 Undo Log:

Lucy ↓ Jack ↓ Tom

找到:

Tom trx_id=100

可见。

返回:

Tom

MVCC解决了什么问题

读不阻塞写

事务A:

UPDATE

事务B

SELECT

不需要等待。


写不阻塞读

读历史版本即可。


大幅提高并发

传统锁机制:

读锁 写锁 互斥

大量等待。


MVCC:

写当前版本 读历史版本

并发能力提升很多。


MVCC在哪些隔离级别生效

Read Uncommitted

不使用MVCC

直接读最新数据。

可能脏读。


Read Committed

使用MVCC。

每次查询生成新的 Read View。

查询1 ReadView1 查询2 ReadView2

所以可能不可重复读。


Repeatable Read(MySQL默认)

使用MVCC。

事务第一次查询生成 Read View。

后续一直使用。

事务开始 ReadView固定 查询1 查询2 查询3

因此实现可重复读。


Serializable

直接加锁。

SELECT 加共享锁

基本不依赖MVCC。


面试总结

如果面试官问:

什么是 MVCC?

可以回答:

MVCC(多版本并发控制)是 InnoDB 实现高并发读写的重要机制,其核心思想是通过保存数据的多个历史版本,让读操作读取符合事务快照的版本,而不是直接加锁等待。

InnoDB 的 MVCC 主要依赖:

  1. 隐藏字段trx_idroll_pointer
  2. Undo Log 构成的版本链
  3. Read View 进行可见性判断

查询时根据 Read View 判断当前版本是否可见,不可见则沿 Undo Log 回溯历史版本,直到找到可见版本。

因此 MVCC 实现了:

读不阻塞写 写不阻塞读 提高并发性能

这也是 MySQL InnoDB 在Read CommittedRepeatable Read隔离级别下实现一致性读的核心原理。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询