一文读懂 Mysql MVCC

💕💕 推荐:体系化学习Java(Java面试专题)

文章目录

  • 1、什么是 MVCC
  • 2、什么是当前读、快照读
  • 3、MVCC 具体解决什么问题
  • 4、MVCC 的实现原理
    • 4.1、4个隐式字段
    • 4.2、undo 日志
    • 4.3、Read View
  • 5、使用 MVCC 时,需要注意什么问题

在这里插入图片描述

1、什么是 MVCC

MVCC(Multi-Version Concurrency Control)是一种多版本并发控制技术,常用于数据库管理系统中,用于支持事务的并发执行。MVCC 技术可以在读取数据时不产生锁,同时保证数据的一致性。具体来说,MVCC 技术会在每个数据行上保存多个版本的数据,每个版本都有一个时间戳,当一个事务需要读取数据时,会根据该事务的时间戳选择合适的数据版本进行读取,从而避免了读取数据时的锁定操作。同时,MVCC 技术还可以通过回滚日志和垃圾回收机制来保证数据的一致性和完整性。MVCC 技术在 InnoDB 存储引擎中得到了广泛的应用,成为了 InnoDB 存储引擎的一个重要特性。

正是因为有了 MVCC,所以 Mysql 的并发性能才会更好。

2、什么是当前读、快照读

当前读和快照读是 InnoDB 存储引擎中的两种读取数据的方式。

当前读:是指在读取数据时,使用的是最新的数据版本。当前读可以通过 SELECT … FOR UPDATE (排它锁)或者 SELECT … LOCK IN SHARE MODE (共享锁)等语句实现。在当前读的情况下,如果其他事务正在修改该数据行,当前读会被阻塞,直到其他事务释放锁。

快照读:是指在读取数据时,使用的是指定时间点的数据版本。快照读可以通过 SELECT … FROM … AS OF 或者 SELECT … FROM … VERSIONS BETWEEN … AND … 等语句实现。在快照读的情况下,如果其他事务正在修改该数据行,快照读不会被阻塞,而是读取该数据行的历史版本。快照读可以提高并发读取数据的效率,但是可能会读取到已经被修改的数据行。

SELECT ... FROM ... AS OF 是一种快照读取数据的方式。它可以在读取数据时指定一个时间点,然后读取该时间点的数据版本,而不是当前的数据版本。这种方式不会对其他事务产生锁定,因此可以提高并发性能。在使用 AS OF 语句时,InnoDB 存储引擎会从回滚日志中读取指定时间点的数据版本,并返回给用户。需要注意的是,使用 AS OF 语句时,需要保证指定的时间点在当前事务开始之前,否则可能会读取到未提交的数据,导致数据不一致。

SELECT ... FROM ... VERSIONS BETWEEN ... AND ... 是一种快照读取数据的方式,可以读取指定时间范围内的数据版本。在使用该语句时,需要指定开始时间和结束时间,然后 InnoDB 存储引擎会读取这个时间范围内的所有数据版本,并将它们返回给用户。这种方式不会对其他事务产生锁定,因此可以提高并发性能。需要注意的是,使用 VERSIONS BETWEEN 语句时,需要保证指定的时间范围在当前事务开始之前,否则可能会读取到未提交的数据,导致数据不一致。

当前读适合于需要修改数据的场景,而快照读适合于只需要读取数据的场景。

3、MVCC 具体解决什么问题

首先说下数据库的并发场景可以分为以下几种:

  1. 读写并发:多个事务同时对同一数据进行读和写操作。这种场景需要使用并发控制机制来保证数据的一致性和完整性。

  2. 写写并发:多个事务同时对同一数据进行写操作。这种场景需要使用锁定机制来保证数据的一致性和完整性。

  3. 读读并发:多个事务同时对同一数据进行读操作。这种场景不需要使用并发控制机制,可以提高数据库系统的并发性能。

  4. 隔离级别并发:不同事务之间的隔离级别不同,可能会导致数据不一致的问题。这种场景需要使用事务隔离级别机制来保证数据的一致性和完整性。

  5. 死锁并发:多个事务之间相互依赖,可能会出现死锁的情况。这种场景需要使用死锁检测和解决机制来避免死锁的发生。

而 MVCC 主要解决数据库系统中的并发控制问题。在多用户并发访问数据库时,如果不进行并发控制,可能会导致数据不一致的问题。传统的并发控制方式是使用锁定机制,即在读取或修改数据时,需要先对数据行进行加锁,防止其他事务同时对该数据行进行修改。这种方式虽然可以保证数据的一致性,但是会降低并发性能,因为同时只有一个事务可以对数据行进行操作。
MVCC 技术通过在每个数据行上保存多个版本的数据,每个版本都有一个时间戳,来实现并发控制。当一个事务需要读取数据时,会根据该事务的时间戳选择合适的数据版本进行读取,从而避免了读取数据时的锁定操作。同时,MVCC 技术还可以通过回滚日志和垃圾回收机制来保证数据的一致性和完整性。MVCC 技术可以提高数据库系统的并发性能,同时保证数据的一致性。

MVCC + 悲观锁:MVCC 解决读写冲突,悲观锁解决写写冲突
MVCC + 乐观锁:MVCC解决读写冲突,乐观锁解决写写冲突

4、MVCC 的实现原理

在这里插入图片描述
MVCC 的实现原理主要是在每个数据行上保存多个版本的数据,并通过版本号和时间戳来实现并发控制。具体实现步骤如下:

  1. 在每个数据行上保存多个版本的数据。每个版本都有一个唯一的版本号和时间戳,用于标识该版本的数据是在何时被修改的。

  2. 当一个事务需要读取数据时,会根据该事务的时间戳选择合适的数据版本进行读取。如果该事务的时间戳早于某个数据版本的时间戳,则该数据版本对该事务不可见,因为该数据版本是在该事务开始之后被修改的。

  3. 当一个事务需要修改数据时,会先将原始数据行复制一份,并在新复制的数据行上进行修改。同时,该事务会生成一个新的版本号和时间戳,并将新版本的数据行插入到数据库中。这样,原始数据行和新数据行就形成了一个版本链。

  4. 当一个事务提交时,会将该事务所修改的数据行的最新版本号和时间戳更新到事务提交记录中。这样,其他事务就可以根据该事务的提交记录来选择合适的数据版本进行读取。

  5. 当一个事务回滚时,会将该事务所修改的数据行的最新版本号和时间戳恢复到事务开始时的状态。这样,其他事务就可以根据该事务的回滚记录来选择合适的数据版本进行读取。

  6. 为了避免版本链过长,数据库系统会定期进行垃圾回收,删除不再需要的版本。这样可以减少数据库系统的存储空间和提高查询性能。

为了解决读写冲突主要是依赖记录中的 4个隐式字段,undo日志 ,Read View 来实现的

4.1、4个隐式字段

MVCC(多版本并发控制)是一种用于数据库系统的并发控制技术,它通过在每个数据行上保存多个版本的数据,每个版本都有一个时间戳,来实现并发控制。在 MVCC 中,每个数据行都有四个隐式字段,分别是:

  1. Transaction ID:事务 ID,表示修改该数据行的事务的 ID。
  2. Rollback Pointer:回滚指针,指向该事务的回滚日志,用于撤销该事务对该数据行的修改。
  3. Row Start:行开始时间戳,表示该数据行的版本开始时间。
  4. Row End:行结束时间戳,表示该数据行的版本结束时间。

在这里插入图片描述

这四个隐式字段是 MVCC 技术实现并发控制的关键,它们记录了每个数据行的修改历史和版本信息,用于支持并发事务的读写操作。当一个事务需要读取数据时,会根据该事务的时间戳选择合适的数据版本进行读取,从而避免了读取数据时的锁定操作。同时,MVCC 技术还可以通过回滚日志和垃圾回收机制来保证数据的一致性和完整性。

4.2、undo 日志

Undo 日志是数据库系统中的一种重要的日志记录机制,用于支持事务的回滚和 MVCC(多版本并发控制)技术的实现。当一个事务执行修改操作时,数据库系统会将修改前的数据记录到 Undo 日志中,以便在事务回滚时可以恢复到修改前的状态。同时,在 MVCC 技术中,Undo 日志还用于保存每个数据行的历史版本信息,以便支持并发事务的读写操作。

下面是一个使用 Undo 日志的 SQL 示例:
假设有一个表 t,其中包含两个字段 id 和 name,现在执行以下 SQL:

UPDATE t SET name = 'new_name' WHERE id = 1;

执行该 SQL 语句时,数据库系统会将 id 为 1 的数据行修改前的值记录到 Undo 日志中。如果事务回滚,则可以使用 Undo 日志将该数据行恢复到修改前的状态。

另外,如果该表使用了 MVCC 技术,在每个数据行中也会保存 Undo 日志,用于支持并发事务的读写操作。当一个事务需要读取数据时,会根据该事务的时间戳选择合适的数据版本进行读取。如果需要回滚该事务,则可以使用 Undo 日志将该数据行恢复到指定的历史版本。

4.3、Read View

Read View 是 MySQL 中用于实现 MVCC 的一种机制,用于支持并发事务的读操作。在 MySQL 中,每个事务都有自己的 Read View,用于确定该事务可以读取到哪些数据版本。Read View 由以下两个部分组成:

  1. Trx ID 列表:该列表记录了当前事务启动时,已经提交的事务 ID 列表。
  2. 快照版本号:该版本号记录了当前事务启动时,数据库系统的快照版本号。

在执行读操作时,MySQL 会将当前事务的 Read View 与数据行的版本信息进行比较,从而确定当前事务可以读取哪些数据版本。如果数据版本早于当前事务的快照版本号或者是由未提交的事务所产生的版本,则当前事务无法读取该数据版本。

以下是一个示例 SQL 语句,说明 Read View 的工作原理:

-- 事务 A
START TRANSACTION;
SELECT * FROM t WHERE id = 1;

 -- 事务 B
START TRANSACTION;
UPDATE t SET name = 'new_name' WHERE id = 1;
COMMIT;

 -- 事务 A
SELECT * FROM t WHERE id = 1;
COMMIT;

在上述示例中,事务 A 在启动时会创建自己的 Read View,并记录当前数据库系统的快照版本号。在第一个 SELECT 语句中,事务 A 会根据自己的 Read View 读取 id 为 1 的数据行,此时由于事务 B 已经对该数据行进行了修改,因此事务 A 无法读取到该数据行的旧版本。

在事务 B 中,执行 UPDATE 语句时,会创建一个新的数据行版本,并将该版本的事务 ID 记录到 redo 日志中。同时,由于该版本的事务 ID 还未提交,因此该版本不会被事务 A 的 Read View 所包含。

在事务 A 中的第二个 SELECT 语句中,由于该语句在事务 A 启动之后执行,因此会使用事务 A 的当前 Read View 进行读取。由于事务 A 的 Read View 不包含事务 B 所提交的事务 ID,因此事务 A 可以读取到 id 为 1 的数据行的旧版本。

5、使用 MVCC 时,需要注意什么问题

  1. 事务启动时间:事务的启动时间会影响到事务能够读取到哪些数据版本。如果事务启动时间早于某个数据版本的创建时间,则该事务可以读取到该数据版本。因此,需要确保事务启动时间在需要读取的数据版本之后。

  2. 版本回收:MVCC 技术需要维护多个数据版本,因此需要定期清理不再需要的版本,避免占用过多的存储空间。在 MySQL 中,使用 purge 线程来定期清理不再需要的版本。

  3. 长事务:长时间运行的事务会占用大量的 MVCC 版本,导致存储空间不足或性能下降。因此,需要避免长时间运行的事务,或者使用合适的事务隔离级别来减少 MVCC 版本的数量。

  4. 并发度:MVCC 技术可以提高数据库系统的并发性能,但是也需要考虑并发度的问题。如果并发度过高,可能会导致 MVCC 版本的数量过多,从而影响性能。

  5. 事务隔离级别:在使用 MVCC 技术时,需要根据具体的业务需求选择合适的事务隔离级别。不同的隔离级别会影响 MVCC 版本的数量和读取的数据版本,从而影响并发性能和数据一致性。需要根据具体的业务需求进行选择。

在这里插入图片描述

💕💕 本文由激流原创,首发于CSDN博客,博客主页 https://blog.csdn.net/qq_37967783?spm=1010.2135.3001.5421
💕💕喜欢的话记得点赞收藏啊

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/27597.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【分布式系统与一致性协议】

分布式系统与一致性协议 CAP原理APCPCA总结BASE理论 一致性拜占庭将军问题 分布式系统是一个硬件或软件组件分布在不同的网络计算机上,彼此之间仅仅通过消息传递进行通信和协调的系统。 分布式系统的设计目标一般包含如下: 可用性:可用性是分…

JavaSE-04【方法】

文章目录 JavaSE-04【方法】第一章 方法1.1 方法定义的格式详解1.2 方法定义的三要素1.3 方法调用的流程图解1.4 方法定义的有无参数1.5 方法定义的有无返回值 第二章 方法调用方式以及注意事项2.1 方法调用的注意事项2.2 调用方法的三种形式 JavaSE-04【方法】 第一章 方法 …

【华为OD机试真题2023B卷 JAVAJS】评论转换输出

华为OD2023(B卷)机试题库全覆盖,刷题指南点这里 评论转换输出 时间限制:1s 空间限制:256MB 限定语言:不限 题目描述: 在一个博客网站上,每篇博客都有评论。每一条评论都是一个非空英文字母字符串。 评论具有树状结构,除了根评论外,每个评论都有一个父评论。 当评论保…

再看const成员函数

文章目录 再看函数重载const成员函数保安(const)能保护所有人(类成员)吗?mutable修饰类成员 const/非const成员函数的复用 关于函数重载实际上我理解不是很深入,直接导致const成员函数这块出大问题&#xf…

chatgpt赋能python:Python如何升序输出?从入门到实践!

Python如何升序输出?从入门到实践! 作为一门高级编程语言,Python是目前应用广泛且最为流行的一门语言之一。它逐渐成为开发者的首选语言,因为它易学易用,可读性强,支持多种编程范式,提供了强大…

【MySQL 数据库】9、存储过程

目录 一、存储过程是什么二、存储过程的基本语法三、MySQL 中的变量(1) 系统变量(2) 用户自定义变量(3) 局部变量 四、if 判断五、参数传递和返回值六、case 语句七、while 循环八、repeat 循环九、loop 循环十、游标十一、条件处理程序 一、存储过程是什么 🌱 存储…

Java反射与注解

文章目录 一、 注解1.简介2. 元注解3. 自定义注解 二、 反射1. 简介2. 理解Class类并获取Class实例3. 类的加载与初始化4. 类加载器ClassLoader5. 获取运行时类的完整结构6. 动态创建对象执行方法7. 反射操作泛型8. 反射操作注解 一、 注解 1.简介 Annotation是JDK5.0开始引入…

第二章 搭建TS环境

搭建 TypeScript 的开发环境。一个舒适、便捷且顺手的开发环境,不仅能大大提高学习效率,也会对我们日常的开发工作有很大帮助。 这一节我们就来介绍 VS Code 下的 TypeScript 环境搭建:插件以及配置项。对于 TS 文件的执行,我们会…

《横向联邦学习中 PCA差分隐私数据发布算法》论文算法原理笔记

论文地址:https://www.arocmag.com/article/01-2022-01-041.html 论文摘要 为了让不同组织在保护本地敏感数据和降维后发布数据隐私的前提下,联合使用 PCA进行降维和数据发布,提出横向联邦 PCA差分隐私数据发布算法。引入随机种子联合协商方…

linuxOPS基础_linux软件包安装

软件包概述 上图是windows下的软件包 Linux下也有很多可以安装的软件,而这些软件的安装包可细分为两种,分别是源码包和二进制包。 Linux下软件的安装方式 ① RPM软件包安装 > 软件名称.rpm ② YUM包管理工具 > yum install 软件名称 -y ③ 源码…

基于QGIS的长株潭城市群边界范围融合实战

背景 在面向区域的研究过程中,比如一些研究区域,如果是具体的行政区划,比如具体的某省或者某市或者县,可以直接从国家官方的地理数据中直接下载就可以。但如果并没有直接的空间数据那怎么办呢?比如之前遇到的一个场景&…

【郭东白架构课 模块二:创造价值】31 |节点六: 如何组织阶段性的价值交付?

你好,我是郭东白。上节课我们讲了为什么要做阶段性的价值交付,以及进入阶段性价值交付环节的准备工作。有了这些学习基础,这节课我们就可以进行阶段性价值交付了。 在交付的过程中,主要有三部分工作:目标分解、定义交…

数据结构——堆(C语言实现)

文章目录 什么是堆堆的实现堆的结构定义堆的初始化接口堆的销毁接口堆的插入数据接口向上调整建堆接口判断堆是否为空堆的删除数据接口向下调整建堆接口获取堆顶数据获取堆的有效数据个数完整实现代码小结 堆排序堆排序的实现 关于建堆和堆排序时间复杂度的分析向下调整建堆向上…

day52|动态规划13-子序列问题

子序列系列问题 300.最长递增子序列 什么是递增子序列: 元素之间可以不连续,但是需要保证他们所在位置是元素在数组中的原始位置。 dp数组dp[i]表示以nums[i]为结尾的最长递增子序列的长度。递归函数:dp[i] max(dp[j]1,dp[j])初始化条件&…

算法刷题-链表-移除链表元素

链表操作中,可以使用原链表来直接进行删除操作,也可以设置一个虚拟头结点再进行删除操作,接下来看一看哪种方式更方便。 203.移除链表元素 力扣题目链接 题意:删除链表中等于给定值 val 的所有节点。 示例 1: 输入&…

Linux下信号量使用总结

目录 1.Linux下信号量简介 2.POSIX信号量 2.1 无名信号量 2.2 有名信号量 3.System V信号量 1.Linux下信号量简介 信号量是解决进程之间的同步与互斥的IPC机制,互斥与同步关系存在的症结在于临界资源。 临界资源是在同一个时刻只容许有限个(一般只有…

【数据结构与算法】03 队列(顺序队列--循环队列--优先级队列--链队列)

一、概念1.1 队列的基本概念1.2 队列的顺序存储结构1.21 顺序队列(静态队列)1.22 循环队列1.23 优先级队列 1.3 队列的链式存储结构 二、C语言实现2.1 顺序存储2.11 顺序队列2.12 循环队列2.13 优先级队列 2.2 链式存储 一、概念 1.1 队列的基本概念 队…

Linux内核中断和Linux内核定时器

目录 Linux内核中断 Linux内核定时器 Linux内核中断 int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev) 功能:注册中断 参数: irq : 软中断号 gpio的软中断号 软中断号 gpio_to_i…

【PCB专题】案例:绕等长怎么直接以颜色区分看出是否绕好

PCB上对于时序的处理,在板卡上实际我们是通过绕等长的手段。做为一个合格的Layout工程师,等长的处理是不可或缺的技能。 一般来说,在绕等长的时候我们可以使用Delay Tune命令来改变走线的长度,然后通过规则管理器中分析看看哪根线长哪根线短。 但是在实际工作中,很可能绕着…

Android应用程序进程的启动过程

Android应用程序进程的启动过程 导语 到这篇文章为止,我们已经简要地了解过了Android系统的启动流程了,其中比较重要的内容有Zygote进程的启动和SystemService以及Launcher的启动,接下来我们将要学习的是Android应用程序的启动过程&#xff…