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. 快照读是如何实现的(快照如何存储?存储在哪?多个快照存在时怎么读?)
相关推荐
abandondyy1 小时前
MySQL---主从复制和读写分离
数据库·mysql
DEARM LINER2 小时前
mysql 巧妙的索引
数据库·spring boot·后端·mysql
不惑_3 小时前
Redis与MySQL双写一致性的缓存模式
redis·mysql·缓存
码农幻想梦3 小时前
实验九 视图的使用
前端·数据库·oracle
影子落人间3 小时前
Oracle创建存储过程,创建定时任务
数据库·oracle
大G哥3 小时前
02、Oracle过滤和排序数据
数据库·oracle
代码吐槽菌5 小时前
基于SSM的汽车客运站管理系统【附源码】
java·开发语言·数据库·spring boot·后端·汽车
伏虎山真人5 小时前
开源数据库 - mysql - 组织结构(与oracle的区别)
数据库·mysql·开源
精致先生6 小时前
问题记录01
java·数据库·mybatis
Channing Lewis6 小时前
salesforce developer console 匿名执行是以什么身份执行的
数据库·安全·salesforce