01_MVCC(多版本并发机制)

news/2024/10/20 1:17:45/

MVCC_0">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_29">事务隔离级别与 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__93">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.ppmy.cn/news/1540383.html

相关文章

利用 Llama 3.1模型 + Dify开源LLM应用开发平台,在你的Windows环境中搭建一套AI工作流

文章目录 1. 什么是Ollama?2. 什么是Dify?3. 下载Ollama4. 安装Ollama5. Ollama Model library模型库6. 本地部署Llama 3.1模型7. 安装Docker Desktop8. 使用Docker-Compose部署Dify9. 注册Dify账号10. 集成本地部署的 Llama 3.1模型11. 集成智谱AI大模型…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-13

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-13 目录 文章目录 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-13目录1. The Cognitive Capabilities of Generative AI: A Comparative Analysis with Human Benchmarks2. WALL-E: World Alig…

Open-WebUI

Open-WebUI特点⭐ ️直观的界面:聊天界面从 ChatGPT 中汲取灵感,确保用户友好的体验。响应式设计:在桌面和移动设备上享受无缝体验。⚡快速响应:享受快速响应的性能。轻松设置:使用 Docker 或 Kubernetes(…

ToB项目身份认证AD集成(完):利用ldap.js实现与windows AD对接实现用户搜索、认证、密码修改等功能 - 以及针对中文转义问题的补丁方法介绍

在前面的两篇文章中,我详细的介绍了使用ldap与window AD服务集成,实现ToB项目中的身份认证集成方案,包括技术方案介绍、环境配置: ToB项目身份认证AD集成(一):基于目录的用户管理、LDAP和Active Directory简述 ToB项目身份认证AD集成(二):一分钟搞定window server 20…

理解C#中空值条件运算符及空值检查简化

前言 .NET 4.6 及以上版本,提供了空值条件运算符 ?. 和 ?[]。这些运算符的引入,为我们提供了一种简明的方式来处理空值的场景、简化空值检查,可避免 NullReferenceExceptions 的异常。本文将探索 C# 的空值检查运算符。 介绍 空值,这里指的是 null。在定义对象后,未对其…

深入了解Vue Router:基本用法、重定向、动态路由与路由守卫的性能优化

文章目录 1. 引言2. Vue Router的基本用法2.1 基本配置 3. 重定向和命名路由的使用3.1 重定向3.2 命名路由 4. 在Vue Router中如何处理动态路由4.1 动态路由的概念4.2 如何处理动态路由4.3 动态路由的懒加载 5. 路由守卫的实现与性能影响5.1 什么是路由守卫?5.2 路由…

2024入门测参考答案(c语言版)

先自己看代码思考,不理解的地方可以截图私聊…… 7-1 祝福祖国! 这是一个编程题模板。 2024年即将到来,作为一名大学生,为了表达在新的一年里,对祖国的祝福,请编写程序输出祝福语:在新的一年…

【Linux】进程ID和线程ID在日志中的体现

在分析内核打印日志流程的时候,发现有时候同一个进程函数调用关系比较混乱(因为只打印了进程号),现象就是一个函数走着走着不知道走哪里去了。 另一个现象是,在Linux启动Firefox的时候,启了大概80个进程&…