当前位置: 首页 > article >正文

01_MVCC(多版本并发机制)

MVCC(多版本并发机制)

文章目录

    • MVCC(多版本并发机制)
        • 简介
        • 工作原理
          • 主要组件
        • 事务隔离级别与 MVCC
        • 实现方式
          • 快照读(Snapshot Read)
          • 当前读(Current Read)
          • 版本链管理
        • 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. 返回结果:返回符合一致性视图的数据版本,确保读取的是事务启动时的快照数据。
-- 事务1:启动事务
START TRANSACTION;
-- 快照读,读取一致性视图中的数据
SELECT * FROM example WHERE id = 1;
当前读(Current Read)

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

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

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

版本链管理

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

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

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


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

示例

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

-- 创建表并插入数据
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. 快照读是如何实现的(快照如何存储?存储在哪?多个快照存在时怎么读?)

http://www.kler.cn/news/357715.html

相关文章:

  • Leetcode 3327. Check if DFS Strings Are Palindromes
  • 2024.09.28校招 实习 内推 面经
  • Spring Boot优化大创项目风险评估流程
  • HarmonyOS 开发知识总结
  • Discuz | 起尔开发 传奇开服表游戏公益服发布论坛网站插件
  • 记一次 Flink mongoDB CDC 到Kafka遇到的问题
  • 2011年国赛高教杯数学建模A题城市表层土壤重金属污染分析解题全过程文档及程序
  • Spring Boot视频网站:构建可扩展的视频服务平台
  • 河源市社保卡照片要求及手机自拍拿数码相片回执的方法
  • select数据备份和恢复
  • 图论day61:最小生成树|最小生成树理论基础:prim算法、kruskal算法(思维导图版)、53.寻宝(卡码网 第七期模拟笔试)
  • 【elasticsearch】安装和启动
  • vmware中使用U盘安装win10系统
  • SpringBoot物流管理系统设计与实现
  • 【数据结构与算法】链表(下)
  • SpringDataRedis快速入门
  • JDK17下,使用SHA1算法报Certificates do not conform to algorithm constraints错误
  • PostgreSQL技术内幕15:物化视图
  • 关于通信设备中的告警相关知识
  • SQL数据库刷题sql_day34(移动平均值、累计求和)