深入浅出MVCC多版本并发控制原理

思考:为什么要用MVCC?我直接使用读写锁来实现数据的一致性不行吗?

​ 很明显是不行的,在高并发的数据库应用中,同时有大量的读写操作。传统的锁机制(如读写锁)在高并发场景下可能会导致大量的锁争用,降低系统性能。
​ MVCC通过维护数据的多个版本,允许读操作和写操作并发进行,减少了锁争用,从而提高系统的并发性能。

1.当前读和快照读

1.1当前读

当前读是指读取数据时,读取的是最新的数据。当前读会读取最新的数据版本,并且可能需要等待其他事务释放锁。

当前读的场景包括:

  • SELECT ... FOR UPDATE
  • SELECT ... LOCK IN SHARE MODE
  • INSERT
  • UPDATE
  • DELETE

这些操作会获取行级锁,以确保读取的是最新的数据,并防止其他事务修改读取的数据行。

实现方式当前读依赖于行级锁和事务机制,以确保读取的是最新的数据版本,并防止其他事务在读取过程中修改数据。

1.2快照读

快照读是指读取数据时,读取的是数据在某个时间点的快照版本。InnoDB存储引擎通过多版本并发控制(MVCC)来实现快照读,读取的数据可能不是最新的数据,而是事务开始时的快照数据。

快照读是默认的SELECT读操作,在事务隔离级别为可重复读(REPEATABLE READ)**或更低(例如**读已提交(READ COMMITTED))时,执行普通的SELECT语句都是快照读。

快照读的优点

  • 不需要等待锁,避免了读写操作的冲突,提高了并发性能。
  • 可以实现一致性读取,事务在整个过程中看到的数据都是一致的,不受其他事务的影响。

实现方式快照读是通过多版本并发控制(MVCC)实现的。在MVCC机制下,每行数据都有多个版本,存储在数据页中。每个版本的数据都有两个隐藏的时间戳字段:trx_id(事务ID)和roll_pointer(回滚指针)。

2.MVCC是什么?

在这里插入图片描述

3.MVCC实现原理

在这里插入图片描述

3.1隐藏字段

当使用InnoDB存储引擎创建一张表时,系统会自动为每一行数据添加一些隐藏字段,以支持MVCC和事务管理。

在这里插入图片描述

  • trx_id,当一个事务对某条聚簇索引记录进行改动时,就会把该事务的事务 id 记录在 trx_id 隐藏列里
  • roll_pointer,每次对某条聚簇索引记录进行改动时,都会把旧版本的记录写入到 undo 日志中,然后这个隐藏列是个指针,指向每一个旧版本记录,于是就可以通过它找到修改前的记录。

3.2undo版本链

在这里插入图片描述

在MySQL的InnoDB存储引擎中,Undo版本链(Undo Version Chain)是多版本并发控制(MVCC)机制的重要组成部分。Undo版本链通过维护数据的历史版本,支持事务的一致性读取和回滚操作。每当数据被修改时,InnoDB会生成一条回滚日志记录,并将其加入到版本链中,从而形成一个历史版本链条。

3.3readview

Read View 到底是个什么东西?

在这里插入图片描述

Read View 有四个重要的字段:

  • m_ids :指的是在创建 Read View 时,当前数据库中「活跃事务」的事务 id 列表,注意是一个列表,“活跃事务”指的就是,启动了但还没提交的事务
  • min_trx_id :指的是在创建 Read View 时,当前数据库中「活跃事务」中事务 id 最小的事务,也就是 m_ids 的最小值。
  • max_trx_id :这个并不是 m_ids 的最大值,而是创建 Read View 时当前数据库中应该给下一个事务的 id 值,也就是全局事务中最大的事务 id 值 + 1;
  • creator_trx_id :指的是创建该 Read View 的事务的事务 id

3.4隐藏字段+undo版本链+readview 如何实现MVCC(如何决定返回什么数据)

在这里插入图片描述

隐藏字段 + undo版本链 ----------------------------------------->返回的数据
readview + 版本链访问规则/可见性算法 ------------------->返回数据的版本

在这里插入图片描述

4.MVCC概述

宏观:MySql的InnoDB存储引擎下RC、RR且快照读下基于MVCC做数据的多版本并发控制。

在这里插入图片描述

5.MVCC在RC和RR级别下不同表现

在这里插入图片描述

6.MVCC解决了什么问题

6.1解决了读写阻塞

  • 在传统的数据库系统中,当一个事务正在读取数据时,如果其他事务同时对同一数据进行写操作,就会导致读-写冲突。
  • MVCC通过为每个事务提供一致性的数据视图,允许事务在读取数据时不被写操作所阻塞,从而减少了读-写冲突,提高了并发性能。

在这里插入图片描述

6.2在RR快照读下解决了幻读问题(大部分)

可重复读隔离级是由 MVCC(多版本并发控制)实现的,实现的方式是开始事务后(执行 begin 语句后),在执行第一个查询语句后,会创建一个 Read View,后续的查询语句利用这个 Read View,通过这个 Read View 就可以在 undo log 版本链找到事务开始时的数据,所以事务过程中每次查询的数据都是一样的,即使中途有其他事务插入了新纪录,是查询不出来这条数据的,所以就很好了避免幻读问题。

思考:那在RR级别下,当前读没有采用MVCC,那他是如何解决幻读问题的?(MySql默认的隔离级别是RR)

Innodb 引擎为了解决「可重复读」隔离级别使用「当前读」而造成的幻读问题,就引出了间隙锁
假设,表中有一个范围 id 为(3,5)间隙锁,那么其他事务就无法插入 id = 4 这条记录了,这样就有效的防止幻读现象的发生。

  • 10
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值