一文读懂 Mysql MVCC

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

博主介绍: ✌博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家✌

Java知识图谱点击链接:体系化学习Java(Java面试专题)

💕💕 感兴趣的同学可以收藏关注下不然下次找不到哟💕💕

1686575276531.jpg

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:行结束时间戳,表示该数据行的版本结束时间。

image.png

这四个隐式字段是 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 版本的数量和读取的数据版本,从而影响并发性能和数据一致性。需要根据具体的业务需求进行选择。

1686494501743.jpg

💕💕 本文由激流丶创作,原创不易,感谢支持!
💕💕喜欢的话记得点赞收藏啊!

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
6天前
|
关系型数据库 MySQL
|
6天前
|
Oracle 关系型数据库 MySQL
MySQL相关(六)- 事务隔离级别的实现方案(MVCC)
MySQL相关(六)- 事务隔离级别的实现方案(MVCC)
44 0
|
6天前
|
存储 缓存 关系型数据库
⑩⑧【MySQL】InnoDB架构、事务原理、MVCC多版本并发控制
⑩⑧【MySQL】InnoDB架构、事务原理、MVCC多版本并发控制
114 0
|
6天前
|
存储 SQL 关系型数据库
MySQL事务底层原理和MVCC机制
MySQL事务底层原理和MVCC机制
42 1
|
6天前
|
存储 关系型数据库 MySQL
mysql数据库 mvcc
mysql数据库 mvcc
|
6天前
|
存储 SQL 关系型数据库
MySQL - 深入理解 MySQL 的 MVCC 及实现原理
MySQL - 深入理解 MySQL 的 MVCC 及实现原理
211 0
|
6天前
|
存储 缓存 关系型数据库
Mysql 专栏 - MVCC机制
Mysql 专栏 - MVCC机制
70 0
|
6天前
|
SQL 关系型数据库 MySQL
MySQL事务原理分析(ACID特性、隔离级别、锁、MVCC、并发读异常、并发死锁以及如何避免死锁)
MySQL事务原理分析(ACID特性、隔离级别、锁、MVCC、并发读异常、并发死锁以及如何避免死锁)
106 1
|
9月前
|
算法 关系型数据库 MySQL
MySQL事务隔离实现原理,多版本并发控制MVCC
MySQL事务隔离实现原理,多版本并发控制MVCC
144 0
|
6天前
|
SQL 关系型数据库 MySQL
从 MySQL 的事务 到 锁机制 再到 MVCC
转眼又一年~~2023马上就要到尾声了,在最后的几天中,我想给大家分享一下 MySQL 的一些小知识。在MySQL InnoDB引擎层面,又有新的解决方案 (解决加锁后读写性能问题),叫做MVCC(Multi-Version Concurrency Control)多版本并发控制。在MVCC下,就可以做到读写不阻塞且避免了类似脏读这样的问题。那MVCC是怎么做的呢?MVCC通过生成数据快照 (Snapshot)并用这个快照来提供一定级别 (语句级或事务级)的一致性读取。
68 3