Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > MySQL MVCC多版本并发控制

MySQL MVCC(多版本并发控制)实现机制详细讲解

作者:xiaolyuh123

MVCC是一种用于管理数据库并发访问的技术,它通过在数据库中存储数据的多个版本来避免读写冲突,从而提高了数据库的并发性能,这篇文章主要介绍了MySQL MVCC(多版本并发控制)实现的相关资料,需要的朋友可以参考下

前言

MVCC(Multi-Version Concurrency Control,多版本并发控制)是InnoDB存储引擎解决读写冲突、提升并发性能的核心技术——它通过为数据行维护多个版本(快照),让读操作(SELECT)无需加锁即可读取数据,实现读不阻塞写、写不阻塞读的高并发效果。

一、MVCC核心概念

1.1 什么是MVCC

MVCC是InnoDB专为读已提交(RC)可重复读(RR) 隔离级别设计的并发控制机制,核心特征如下:

1.2 MVCC的核心目标

二、MVCC实现的三大基础组件

InnoDB的MVCC依赖行记录隐藏字段Undo Log(回滚日志)Read View(读视图) 三大核心组件,三者协同完成多版本数据的管理和读取。

2.1 行记录的隐藏字段

InnoDB为每一行数据(除自定义字段外)自动添加3个隐藏字段,是MVCC的基础:

隐藏字段字段类型核心作用
DB_TRX_ID6字节记录最后一次插入/更新该行数据的事务ID(删除视为特殊的更新,标记删除);
DB_ROLL_PTR7字节回滚指针,指向该行数据的Undo Log版本链(通过该指针可回溯历史版本);
DB_ROW_ID6字节聚簇索引无主键/唯一键时,InnoDB自动生成的行ID(仅用于标识行,非MVCC核心);

示例

假设有表user(id INT PRIMARY KEY, name VARCHAR(20)),插入一行(1, '张三'),该行的实际存储结构为:

idnameDB_TRX_IDDB_ROLL_PTRDB_ROW_ID
1张三100指向Undo LogNULL

(注:DB_TRX_ID=100表示插入该记录的事务ID为100)

2.2 Undo Log(回滚日志)

Undo Log是InnoDB在修改数据时,记录的“数据修改前的快照”,是实现版本链的核心载体。

2.2.1 Undo Log的类型

2.2.2 版本链(Version Chain)

每次更新行数据时,InnoDB会按以下步骤维护版本链:

  1. 将更新前的数据写入Update Undo Log
  2. 更新行记录的DB_TRX_ID为当前事务ID;
  3. 更新行记录的DB_ROLL_PTR,指向刚生成的Update Undo Log
  4. 多次更新后,DB_ROLL_PTR会串联所有历史版本,形成版本链(链头是最新版本,链尾是最早版本)。

版本链示例

当前行版本(DB_TRX_ID=102) → DB_ROLL_PTR → 版本1(DB_TRX_ID=101) → DB_ROLL_PTR → 版本0(DB_TRX_ID=100)

2.3 Read View(读视图)

Read View是事务执行快照读时,生成的一个“可见性判断规则”,核心作用是:判断当前事务能看到哪些版本的数据

2.3.1 Read View的核心字段

Read View包含4个关键字段,用于版本可见性判断:

字段名含义
m_ids生成Read View时,当前活跃的事务ID集合(未提交的事务ID);
min_trx_idm_ids中的最小事务ID(活跃事务的最小ID);
max_trx_id系统下一个要分配的事务ID(大于当前所有已分配的事务ID);
creator_trx_id创建该Read View的事务ID(当前执行快照读的事务ID);

2.3.2 版本可见性判断规则

事务读取行数据时,通过Read View判断该行的某个版本是否可见:
假设待判断版本的DB_TRX_ID = trx_id,规则如下:

  1. trx_id < min_trx_id:该版本由“已提交的事务”生成,可见
  2. trx_id >= max_trx_id:该版本由“未来的事务”生成(当前事务未开始时,该事务还未创建),不可见
  3. min_trx_id ≤ trx_id < max_trx_id
    • trx_id ∈ m_ids:该版本由“当前活跃的未提交事务”生成,不可见
    • trx_id ∉ m_ids:该版本由“已提交的事务”生成,可见
  4. 若版本不可见,则通过DB_ROLL_PTR回溯版本链,直到找到第一个可见的版本(或无可见版本)。

三、MVCC核心执行逻辑(以RR隔离级别为例)

以MySQL默认的可重复读(RR) 隔离级别为例,拆解MVCC在INSERT/UPDATE/DELETE/SELECT中的执行流程。

3.1 数据插入(INSERT)

  1. 事务T1(ID=100)执行INSERT INTO user(id, name) VALUES (1, '张三')
  2. InnoDB为该行数据写入DB_TRX_ID=100DB_ROLL_PTR=NULL(无历史版本);
  3. 生成Insert Undo Log(仅用于事务回滚,提交后删除);
  4. 事务提交后,该行数据的版本仅对已提交的事务可见。

3.2 数据更新(UPDATE)

  1. 事务T2(ID=101)执行UPDATE user SET name='李四' WHERE id=1
  2. InnoDB先将该行当前版本(DB_TRX_ID=100)写入Update Undo Log
  3. 更新行记录的DB_TRX_ID=101DB_ROLL_PTR指向刚生成的Update Undo Log
  4. 此时版本链:当前版本(101)→ 历史版本(100);
  5. 事务提交后,Update Undo Log保留,供其他事务读取历史版本。

3.3 数据删除(DELETE)

DELETE被InnoDB视为“特殊的UPDATE”,执行流程如下:

  1. 事务T3(ID=102)执行DELETE FROM user WHERE id=1
  2. InnoDB将该行当前版本写入Update Undo Log
  3. 更新行记录的DB_TRX_ID=102,并标记“删除标识”(物理删除由Purge线程异步完成);
  4. 版本链新增一条:当前版本(102,标记删除)→ 版本1(101)→ 版本0(100)。

3.4 数据读取(SELECT,快照读)

假设当前有活跃事务ID:101、102,事务T4(ID=103)执行SELECT * FROM user WHERE id=1(RR隔离级别):

  1. T4第一次执行SELECT时,生成Read View:
    • m_ids = {101, 102}min_trx_id=101max_trx_id=104creator_trx_id=103
  2. 读取行数据的当前版本(DB_TRX_ID=102),判断可见性:
    • 102 ≥ min_trx_id(101)102 < max_trx_id(104),且102 ∈ m_ids → 不可见;
  3. 通过DB_ROLL_PTR回溯版本链,读取上一个版本(DB_TRX_ID=101):
    • 101 ∈ m_ids → 不可见;
  4. 继续回溯到版本0(DB_TRX_ID=100):
    • 100 < min_trx_id(101) → 可见;
  5. 返回该版本的数据(name='张三');
  6. RR隔离级别下,T4后续的SELECT会复用该Read View,因此多次读取结果一致(可重复读)。

四、不同隔离级别下的MVCC行为

MVCC仅在读已提交(RC)可重复读(RR) 隔离级别生效,核心区别是Read View的创建时机

隔离级别Read View创建时机读取结果特点
读已提交(RC)每次执行快照读(SELECT)时,重新创建Read View同一事务内多次SELECT可能读取到不同版本(不可重复读),仅能看到已提交的最新版本;
可重复读(RR)事务内第一次执行快照读时创建Read View,后续复用同一事务内多次SELECT读取结果一致(可重复读),仅能看到事务启动时已提交的版本;
读未提交(RU)不使用MVCC,直接读取最新数据(无版本控制)能看到未提交事务的数据,存在脏读;
串行化(SERIALIZABLE)禁用MVCC,所有读操作加表锁完全串行执行,无并发冲突,但性能极低;

五、MVCC的优势与局限

5.1 优势

5.2 局限

总结

  1. 核心依赖:MVCC基于行记录隐藏字段(DB_TRX_ID/DB_ROLL_PTR)、Undo Log版本链、Read View可见性规则实现;
  2. 核心逻辑:更新数据时生成版本链,读取数据时通过Read View判断版本可见性,回溯版本链找到符合规则的版本;
  3. 隔离级别差异:RC每次SELECT创建Read View(不可重复读),RR仅第一次创建(可重复读);
  4. 核心价值:实现“读不阻塞写、写不阻塞读”,是InnoDB高并发的核心保障。

到此这篇关于MySQL MVCC(多版本并发控制)实现机制的文章就介绍到这了,更多相关MySQL MVCC多版本并发控制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文