01_MVCC(多版本并发机制)

MVCC(多版本并发机制)

文章目录

简介

MySQL 中的 MVCC(Multi-Version Concurrency Control,多版本并发控制)是一种用于实现高并发、低冲突数据访问的技术。它通过维护数据的多个版本来实现读写操作的并发控制,它允许多个事务同时对同一数据进行读取和修改,而不会互相干扰,从而实现了非阻塞的读操作,降低了写操作的冲突。MVCC 在 InnoDB 存储引擎中得到了实现,是实现 ACID(原子性、一致性、隔离性、持久性)属性中隔离性的关键。

在并发场景下,可能出现三种情况:读-读并发读-写并发写-写并发。在没有写的情况下 读-读并发 是不会出现问题的,而 写-写并发 这种情况比较常用的就是通过加锁的方式实现。那么,读-写并发 则可以通过 MVCC 的机制解决。


工作原理

MVCC 的基本思想是通过存储每行数据的多个版本,实现并发控制,允许读操作和写操作并发执行,避免大部分加锁操作。

主要组件
  1. 隐藏列
    • trx_id:每行记录的创建或最后一次修改该行数据的事务ID。
    • roll_pointer:指向该行数据的上一个版本的指针,用于形成版本链。
  2. 回滚日志(Undo Log)
    • 每次事务修改数据时,旧版本数据会被保存在回滚日志中,形成一个版本链。
    • 用于事务回滚和快照读时的数据读取。
  3. 读视图(Read View)
    • 事务启动时生成的快照视图,用于确定在事务期间可见的数据版本。
    • 确保在可重复读隔离级别下读取到一致性数据。

事务隔离级别与 MVCC

不同的事务隔离级别对 MVCC 的行为有不同的要求:

  1. 读未提交(Read Uncommitted)
    • 不使用 MVCC,读取未提交的数据,可能会出现脏读。
  2. 读已提交(Read Committed)
    • 每次读取最新提交的数据版本(即一个事务中的每一次 SELECT 都会重新获取一次 ReadView),不使用快照视图,可能会出现不可重复读。
  3. 可重复读(Repeatable Read)
    • 使用 MVCC,事务在启动时创建一致性视图,读取该视图的快照数据(即一个事务中只有第一次 SELECT 会读取 ReadView),避免不可重复读和幻读问题。
  4. 串行化(Serializable)
    • 强制事务串行执行,通过加锁实现,不使用 MVCC。

实现方式
快照读(Snapshot Read)

​ 快照读是指读取一致性视图中的数据,不加锁。具体流程如下:

  1. 事务启动:在事务启动时,InnoDB 创建一个一致性视图(Read View),记录当前系统中活跃事务的 ID。
  2. 读取数据 :读取数据时,根据隐藏列 trx_idroll_pointer 形成的版本链,查找符合当前一致性视图的数据版本。
  3. 返回结果:返回符合一致性视图的数据版本,确保读取的是事务启动时的快照数据。
sql 复制代码
-- 事务1:启动事务
START TRANSACTION;
-- 快照读,读取一致性视图中的数据
SELECT * FROM example WHERE id = 1;
当前读(Current Read)

​ 当前读是指读取最新的数据版本并加锁,确保数据的一致性。具体操作包括:

  • SELECT ... FOR UPDATE:读取数据并加排他锁,阻止其他事务的读写操作。
  • SELECT ... LOCK IN SHARE MODE:读取数据并加共享锁,允许其他事务的读操作,但阻止写操作。
  • INSERT、UPDATE、DELETE:对数据进行修改,必须读取最新版本的数据并加锁。
SQL 复制代码
-- 事务1:启动事务
START TRANSACTION;
-- 当前读,加排他锁
SELECT * FROM example WHERE id = 1 FOR UPDATE;

​ 可以说,快照读是 MVCC 实现的基础,而当前读是悲观锁实现的基础

版本链管理

​ 每次数据修改操作时,InnoDB 会创建一个新版本的记录,并通过 roll_pointer 指向旧版本,形成版本链。

sql 复制代码
-- 事务2:启动事务并更新数据
START TRANSACTION;
UPDATE example SET value = 'B' WHERE id = 1;
COMMIT;

在上述操作中,InnoDB 会将旧版本的 value = 'A' 存储在回滚日志中,新版本的 value = 'B' 记录当前事务ID,并指向旧版本。


MVCC 的优缺点
优点
  1. 高并发性能:读操作无需加锁,减少锁争用,提高系统并发性能。
  2. 数据一致性:通过一致性视图,实现可重复读和读已提交隔离级别下的数据一致性,避免脏读和不可重复读问题。
缺点
  1. 存储开销:维护多个版本的数据和回滚日志,增加存储需求。
  2. 数据清理:需要定期清理无用的旧版本数据,增加系统维护复杂性。

示例

以下示例展示了 MVCC 在可重复读隔离级别下的工作方式:

sql 复制代码
-- 创建表并插入数据
CREATE TABLE example (
    id INT PRIMARY KEY,
    value VARCHAR(50)
);

INSERT INTO example (id, value) VALUES (1, 'A');

-- 事务1:启动事务并读取数据
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
SELECT * FROM example WHERE id = 1; -- 读取数据,创建一致性视图

-- 事务2:启动事务并更新数据
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
UPDATE example SET value = 'B' WHERE id = 1;
COMMIT;

-- 事务1:再次读取数据
SELECT * FROM example WHERE id = 1; -- 仍然读取旧版本数据 'A'
COMMIT;

在这个示例中,事务1 启动后创建的一致性视图确保其读取的数据在事务期间保持不变,即使事务2 更新了数据。


总结

MySQL 中的 MVCC 机制通过维护数据的多个版本,实现高并发、低冲突的数据访问。它通过隐藏列、回滚日志和一致性视图等机制,在确保数据一致性的同时,提高了系统的并发性能。通过理解 MVCC 的工作原理和实现方式,可以更好地应用和优化 MySQL 数据库。


延伸
  1. MVCC 机制中的版本链管理是如何实现的
  2. 快照读是如何实现的(快照如何存储?存储在哪?多个快照存在时怎么读?)
相关推荐
Zzz 小生2 小时前
Claude Code学习笔记(四)-助你快速搭建首个Python项目
大数据·数据库·elasticsearch
nongcunqq5 小时前
abap 操作 excel
java·数据库·excel
rain bye bye6 小时前
calibre LVS 跑不起来 就将setup 的LVS Option connect下的 connect all nets by name 打开。
服务器·数据库·lvs
冻咸鱼6 小时前
MySQL的配置
mysql·配置
阿里云大数据AI技术7 小时前
云栖实录|MaxCompute全新升级:AI时代的原生数据仓库
大数据·数据库·云原生
不剪发的Tony老师7 小时前
Valentina Studio:一款跨平台的数据库管理工具
数据库·sql
weixin_307779138 小时前
在 Microsoft Azure 上部署 ClickHouse 数据仓库:托管服务与自行部署的全面指南
开发语言·数据库·数据仓库·云计算·azure
六元七角八分8 小时前
pom.xml
xml·数据库
虚行8 小时前
Mysql 数据同步中间件 对比
数据库·mysql·中间件
奥尔特星云大使8 小时前
mysql读写分离中间件Atlas安装部署及使用
数据库·mysql·中间件·读写分离·atlas