一文读懂MVCC:数据库中的并发读写利器!|环球快看

来源:哔哩哔哩 发布时间:2023-06-04 06:14:12

大家好,我是你们的小米,一个积极活泼、喜好分享技术的小伙伴。今天,我想和大家聊一聊数据库领域的一个重要话题——MVCC多版本并发控制。MVCC是MySQL和其他一些数据库系统中常用的并发控制技术,通过它,我们可以在高并发读写的场景中提高数据库的性能。让我们一起来深入了解吧!

什么是MVCC

MVCC全称为Multi-Version Concurrency Control,中文翻译为多版本并发控制。它是一种用于数据库系统中处理并发读写操作的技术。MVCC通过为每个读写操作创建多个版本的数据来解决并发冲突,从而实现了读操作与写操作之间的并发执行,提高了数据库的并发性能。


【资料图】

什么是当前读

在MVCC中,当前读操作是指读取最新数据版本的操作。下面是一些常见的当前读语句:

SELECT ... FOR UPDATE:用于读取数据并获取写锁。

SELECT ... LOCK IN SHARE MODE:用于读取数据并获取读锁。

什么是快照读

快照读是指读取历史数据版本的操作,也可以称为非锁定读操作。下面是一些常见的快照读语句:

SELECT:普通的查询语句,用于读取数据。

当前读、快照读、MVCC之间的关系

当前读和快照读是MVCC中两种不同的读操作方式。当前读获取的是最新的数据版本,可以用于读写冲突的处理,而快照读获取的是历史的数据版本,用于读取一致性的数据视图。MVCC通过管理和维护这些不同版本的数据,实现了并发读写操作

MVCC解决的问题

数据库并发场景有三种,分别是:

读读冲突:多个读操作之间不会产生冲突,可以并发执行。

读写冲突:读操作不会被写操作所阻塞,读操作可以读取到之前的数据版本,保证了读的一致性。

写写冲突:写操作之间不会产生冲突,可以并发执行。

MVCC是一种用来解决读写冲突的无所并发控制,也就是为事务分配单项增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库的快照,所以MVCC可以为数据库解决以下问题:

并发读写性能提升:在并发读写数据库时,MVCC可以做到在读操作时不用阻塞写操作,在写操作时不用阻塞读操作,提高了数据库并发读写的性能。

事务隔离:MVCC可以解决脏读、幻读、不可重复读等事务隔离的问题,但是不能解决更新丢失问题。

MVCC实现原理

MVCC的实现原理主要依赖于记录中的三个隐藏字段、undolog、read view来实现的。

隐藏字段

MVCC通过在数据表中添加一些隐藏字段来实现多版本控制。这些隐藏字段包括:

DB_TRX_ID:用于标识事务的唯一ID。

DB_ROLL_PTR:指向undo log中的回滚段指针。

DB_ROW_ID:用于唯一标识一行数据。

undolog

undolog是MVCC实现中的一个重要组件,用于记录数据的修改历史。在MVCC中,insert操作和update/delete操作都会产生对应的undolog。

insert操作:在插入一行数据时,会生成一条insert类型的undolog,记录了插入数据的操作。

update和delete操作:在更新或删除一行数据时,会生成一条delete类型的undolog,记录了删除或修改之前的数据。

read view

read view是MVCC中用于管理数据版本的重要概念,它是一个逻辑数据视图。下面是一些关于read view的重要信息:

Read View的定义:Read view是一个事务开始时创建的数据视图,用于确定事务的隔离级别和可见性规则。

Read View的作用:Read view用于确定一个事务可以看到哪些数据版本,以及其他事务是否可以看到该事务修改的数据。

Read View中三个全局属性

在MVCC中,Read view具有三个全局属性,分别是trx_list、up_limit_id和low_limit_id。

trx_list:记录了当前活动的事务列表,其中每个事务包含一个事务ID和一个读视图。

up_limit_id:是一个全局的递增ID,用于判断事务的可见性。

low_limit_id:是一个全局的递增ID,用于判断事务的可见性。

Read View的可见性比较规则

基于上述三个全局属性,Read View的可见性比较规则如下:

如果DB_TRX_ID < up_limit_id,则当前事务能看到DB_TRX_ID 所在的记录,如果大于等于进入下一个判断;

如果 DB_TRX_ID ≥ up_limit_id,则代表 DB_TRX_ID 所在的记录在 Read View 生成后才出现的,那么对于当前事务肯定不可见,如果小于,则进入下一步判断;

判断 DB_TRX_ID 是否在活跃事务中,如果在,则代表在Read View 生成时刻,这个事务还是活跃状态,还没有 commit,修改的数据,当前事务也是看不到;如果不在,则说明这个事务在 Read View 生成之前就已经开始 commit,那么修改的结果是能够看见的。

MVCC的整体处理流程

假设有四个事务T1、T2、T3和T4,它们按顺序开始执行,并进行读写操作。MVCC的整体处理流程如下:

T1开始执行时,创建一个新的read view,并设置up_limit_id和low_limit_id为无穷大。

T1执行读操作,获取到数据库中的数据版本。

T1执行写操作,修改数据库中的数据,并生成对应的undolog。

T1提交事务,将up_limit_id设置为T1的事务ID。

T2开始执行时,创建一个新的read view,并设置up_limit_id为无穷大,low_limit_id为T1的事务ID。

T2执行读操作,根据read view获取到数据库中的数据版本。

T3开始执行时,创建一个新的read view,并设置up_limit_id为无穷大,low_limit_id为T1的事务ID。

T3执行写操作,修改数据库中的数据,并生成对应的undolog。

T4开始执行时,创建一个新的read view,并设置up_limit_id为无穷大,low_limit_id为T1的事务ID。

T4执行读操作,根据read view获取到数据库中的数据版本。

通过上述流程,MVCC保证了不同事务之间的并发读写操作,并根据每个事务的read view确定数据的可见性。

RC、RR级别下的InnoDB快照读区别

在InnoDB中,RC(Read Committed)和RR(Repeatable Read)是两种常见的隔离级别。在这两种隔离级别下,InnoDB的快照读有以下不同之处:

在RR级别下,每个事务的read view是在事务开始时创建的,并在整个事务期间保持不变。这意味着在RR级别下,事务可以看到之前读取的数据版本,即使其他事务已经修改了数据。

在RC级别下,每个语句都会创建一个新的read view,并在执行语句期间保持不变。这意味着在RC级别下,事务每次读取数据都会使用新的read view,而不会看到其他事务已经修改的数据。

RR级别下的快照读会导致更多的数据版本被保留在undo log中,因为每个事务的read view都需要保留。而在RC级别下,每个语句的read view只需要保留一次,因此占用的存储空间较少。

总结:在RC隔离级别下,是每个快照读都会生成并获取最新的 Read View;而在RR隔离级别下,则是同一个事务中的第一个快照读会创建 Read View,之后的快照读获取的都是同一个 Read View。

总结

MVCC多版本并发控制是一种提高数据库并发性能的重要技术。通过使用当前读和快照读,MVCC能够解决读读、读写和写写冲突,并提高并发读写数据库的性能。它还能解决事务隔离的问题,但无法解决更新丢失问题。MVCC的实现原理涉及隐藏字段、undolog和read view等组件,通过管理这些组件,实现了并发读写操作。在不同的隔离级别下,快照读的行为也会有所不同。RR级别下的快照读可以看到之前读取的数据版本,而RC级别下的快照读每次读取都使用新的read view。

END

对于数据库开发和性能优化来说,了解和掌握MVCC技术是非常重要的。希望本篇文章能给大家带来一些启发和帮助。如果有任何问题或者想法,欢迎留言讨论!

标签:

Copyright ©  2015-2022 北冰洋饰品网版权所有  备案号:沪ICP备2020036824号-3   联系邮箱:562 66 29@qq.com