一文彻底弄懂MySQL的MVCC多版本控制器

InnoDB 的 MVCC(Multi-Version Concurrency Control,多版本并发控制) 是 MySQL 实现高并发事务处理的一种机制。通过 MVCC,InnoDB 可以在高并发环境下支持 事务隔离 ,并提供 非阻塞的读操作,从而避免锁定所有读操作带来的性能瓶颈。MVCC 允许事务在不加锁的情况下读取数据,保证了性能和一致性。

一、MVCC 基础概念

MVCC 的核心思想是 通过保存数据的多个版本 来支持并发读写。每个事务在读取数据时看到的是某个数据的特定版本,而不是当前最新的值。这个机制依赖于 Undo Log ,通过保存每一行记录的历史版本来支持多版本读取。(undolog)

  • 读写分离:MVCC 的主要特性是读取数据不阻塞写操作,写操作也不阻塞读取操作。实现了读写分离,提升了数据库并发处理能力。
  • 时间戳版本管理 :每个事务都有一个唯一的 事务 ID(Transaction ID,简称 trx_id,InnoDB 使用事务 ID 来区分数据的不同版本。

二、MVCC 读操作的两种类型

  1. 快照读(Snapshot Read) :读取的是历史版本的数据,是不加锁的普通读取操作。快照读是 MVCC 实现并发读的基础。
    • 比如 SELECT * FROM table WHERE id = 1;,执行的是不加锁的快照读操作。
  2. 当前读(Current Read) :读取的是最新版本的数据,并加锁保证数据的一致性和事务隔离。当前读通常伴随着写操作。
    • 比如 SELECT * FROM table WHERE id = 1 FOR UPDATE;,执行的是加锁的当前读操作。

三、MVCC 的工作原理

InnoDB 通过 行版本控制 来管理数据的不同版本。每一行数据在 InnoDB 的行记录中都包含两个隐藏的字段:

  • trx_id:表示最后一次对该行进行修改的事务 ID。
  • roll_pointer:指向该行之前的版本(即 Undo Log 中的记录),通过该指针可以找到数据的历史版本。

1. 事务的开始与结束

  • 每个事务在开始时会生成一个唯一的事务 ID trx_id
  • 在事务读取数据时,InnoDB 会根据 MVCC 机制判断该事务应该看到哪个版本的数据,主要依赖于事务的隔离级别(如 Read CommittedRepeatable Read)。

2. 数据的修改与版本管理

当一个事务修改数据时,InnoDB 会将当前数据的旧版本保存到 Undo Log 中,并在数据行中更新最新的 trx_idroll_pointer。这样即使数据被更新,其他未提交的事务依然可以通过 Undo Log 访问到旧版本的数据。

每行数据都会有多个历史版本,并通过 roll_pointer 链接到这些历史版本。

3. 版本链

版本链是基于 trx_idroll_pointer 建立的,即每次修改数据时,会在 Undo Log 中存储旧版本,行记录会指向旧版本。版本链的结构如下:

复制代码
最新记录 <-- trx_id_x --trx_id_y --trx_id_z... --> 历史版本

当事务读取数据时,会根据事务的隔离级别、当前事务的 trx_id 以及数据的 trx_id 来决定应该读取哪个版本。

四、MVCC 与事务隔离级别的关系

InnoDB 的 MVCC 机制在不同的事务隔离级别下有不同的行为表现:

  1. Read Committed (读取已提交):事务只会看到其他事务已经提交的版本,每次查询都会读取最新的已提交数据。这种隔离级别下,事务间存在不可重复读问题。
    • 每次查询时,InnoDB 都会返回当前已经提交的最新版本数据。
  2. Repeatable Read (可重复读,MySQL 默认隔离级别):事务在整个过程中看到的是同一个版本快照的数据,即便有其他事务提交了新的数据,当前事务依然看到自己开始时的一致性快照。
    • 事务开始时,InnoDB 会为事务创建一个 一致性视图(consistent view),之后的所有查询都会返回该视图中的数据,保证了可重复读。

隔离级别与 MVCC 读方式的关系

  • Read Committed:每次读取都基于当前已经提交的最新版本,因此快照读是每次返回最新的数据。
  • Repeatable Read:快照读总是基于事务启动时的版本快照,因此即便其他事务提交了新的数据,当前事务依然看到的是旧数据,直到它自己提交。

五、MVCC 的实现细节

1. 事务 ID 与版本控制

InnoDB 使用事务 ID(trx_id)来区分不同事务对数据的修改。每次修改都会将当前事务的事务 ID 记录在该行数据的 trx_id 字段中。通过事务 ID,InnoDB 可以判断当前事务是否能够看到某一行数据的特定版本。

2. 一致性视图

一致性视图(Consistent Read View)是指当前事务只能看到事务启动时的数据快照,除非事务使用的是当前读。InnoDB 会根据当前事务的事务 ID 和一致性视图来确定读取哪一个版本的数据。

  • 对于快照读:根据事务的开始时间戳、其他事务的提交情况,来判断该事务看到的是哪个版本的数据。
  • 对于当前读:必须是最新的数据,InnoDB 会为当前事务加锁,防止其他事务修改或读取。

3. Undo Log 与 Rollback Segment

当一个事务修改数据时,InnoDB 会将原始的数据版本存入 Undo Log 中,Undo Log 中记录了数据的历史版本。通过 roll_pointer,InnoDB 可以在发生并发时,允许其他事务读取数据的旧版本。

六、MVCC 的实际应用场景

1. 电商系统的订单查询

在电商系统中,用户在事务 A 中查询订单时,订单数据可能会被其他事务修改或插入新记录。通过 MVCC,事务 A 查询时看到的订单数据是一致的,即便其他事务插入了新的订单,事务 A 依然能看到一个稳定的订单视图。

2. 金融系统的账户余额查询

在金融系统中,用户账户余额的查询需要确保每次查询得到的结果一致,即使账户余额在后台因某些事务而发生变化,用户也能看到一贯的账户信息,保证用户体验的一致性。MVCC 在这种场景下能保证高并发下的数据一致性。

七、总结

  • MVCC 是 InnoDB 实现高并发事务处理的重要机制,通过维护多版本数据和不加锁的快照读,解决了传统数据库加锁所带来的并发性能问题。
  • MVCC 结合事务的隔离级别,保证数据的 一致性隔离性,使得 MySQL 在高并发场景下依然能保持较高的性能。
  • 通过事务 ID、Undo Log、一致性视图等机制,InnoDB 能够高效地管理事务间的数据访问,从而避免常见的并发读写问题,例如 幻读不可重复读 等。
相关推荐
Fleshy数模3 小时前
CentOS7 安装配置 MySQL5.7 完整教程(本地虚拟机学习版)
linux·mysql·centos
az44yao4 小时前
mysql 创建事件 每天17点执行一个存储过程
mysql
秦老师Q5 小时前
php入门教程(超详细,一篇就够了!!!)
开发语言·mysql·php·db
橘子136 小时前
MySQL用户管理(十三)
数据库·mysql
Dxy12393102166 小时前
MySQL如何加唯一索引
android·数据库·mysql
我真的是大笨蛋6 小时前
深度解析InnoDB如何保障Buffer与磁盘数据一致性
java·数据库·sql·mysql·性能优化
怣506 小时前
MySQL数据检索入门:从零开始学SELECT查询
数据库·mysql
人道领域7 小时前
javaWeb从入门到进阶(SpringBoot事务管理及AOP)
java·数据库·mysql
千寻技术帮8 小时前
10404_基于Web的校园网络安全防御系统
网络·mysql·安全·web安全·springboot
spencer_tseng8 小时前
MySQL table backup
mysql