Mysql神乎乎的MVCC究竟该怎样了解

作者 : 开心源码 本文共2534个字,预计阅读时间需要7分钟 发布时间: 2022-05-14 共142人阅读

引言

MVCC即多版本并发控制主要是为理解决数据库中并发事务读写的一致性问题,那么多个事务并发执行的时候事务的隔离究竟是怎样实现的呢?Mysql默认的RR隔离级别是怎么避免不可重复读的问题呢?我们好好来分析一下。

  • 什么是undo log多版本链

  • MVCC如何保证事务隔离

  • 总结

**一、******什么是undo log多版本链****

Mysql的MVCC机制,以undo log版本链为实现基础。因而要了解MVCC机制,我们得先分析下undo log版本链是个什么东东。Innodb存储引擎给每个数据表都增加了三个隐藏字段:DB_TRX_ID、DB_ROLL_PTR、DB_ROW_ID。

(1)DB_TRX_ID: 标记升级当前数据记录的transaction id,每解决一个事务,其值自动+1。

(2)DB_ROLL_PTR: 回滚指针,记录了最新一次修改该条记录的undo log,回滚的时候就通过这个指针找到undo log回滚。

(3)DB_ROW_ID: 当数据表没有指定主键时,数据库会自动以这个列来作为主键,生成聚集索引。

假设有如下的一条数据,此时这条数据对应的DB_TRX_ID为10,因为之前没有数据,因而回滚指针对应指向空地址。

图片

  每个事务都有自己的一个id,就像其身份证一样唯一标记该事务。当事务启动的时候,向Innodb存储引擎进行申请。假设此时假如打南边来了个事务A,它的事务id为12,事务A对表中的数据字段count进行修改,修改后该条数据对应的事务id为12,同时回滚指针指向实际的undo log回滚日志的地址。

图片

此时打北边又来了个事务B,它的事务id为20,事务B将表中的数据字段count修改为21,对应数据的事务id变为20,回滚指针指向上一条undo log信息。如下图所示:

图片

假如一直有事务进行数据的修改,那么就会形成一条由回滚指针串联的undo log多版本链条。

**二、******MVCC如何保证事务隔离****

阐述完了undo log多版本链条原理,我们知道当一个事务A(事务id=12)升级数据后,当前数据的事务id变为12,同时回滚指针指向undo log数据。每次进行数据升级后,事务id就是修改数据的事务id,同时回滚指针指向回滚数据,最终形成undo log链。但是仅仅依靠undo log多版本链如同并不能实现事务并发执行时的相互隔离,因而我们需要一种机制可以利用undo log多版本链来实现事务隔离。这个机制就是ReadView。Mysql执行事务的时候,会生成一个ReadView,其中会包含以下重要信息:

(1)m_ids:mysql中未提交的事务id集合;

(2)min_trx_id:集合中最小的事务id;

(3)max_trx_id,mysql下一个要生成的事务id,也就是事务id集合中最大的事务id加1;

(4)当前需要执行的事务id;

下面我们来说说Mysql的RR(Repeatable Read )隔离级别就可重复读,读取数据的事务,无论读多少次都是和第一次读取数据取得的值时一样的。我们一起来看下可重复读是如何通过MVCC实现的。  假设现在有事务A以及事务B两个事务,A事务需要读取数据,B事务需要修改数据。

图片

当事务A需要读取数据时,开启ReadView。因为此时数据库活跃的事务为事务A以及事务B,那么对应的ReadView中m_ids={12,34},min_trx_id=12,max_trx_id=35,当前需要执行的事务id为12。此时事务A读取数据时,先判断当前的事务id为12,而数据中的事务id为11,小于当前事务A的id。说明当前读取的数据是在事务A开启之前提交的,因而可以正常进行数据读取。

图片

假如此时事务B进行了数据修改,修改count为29。而事务A再次进行数据读取时,继续进行判断,发现当前数据对应的事务id为34比当前的查询事务要大,但是小于max_trx_id,同时在m_ids中。说明该事务id对应的事务和事务A属于并发执行事务,因而不能进行数据读取。则根据undo log版本链,往上寻觅undo log信息。假如找到的事务id小于当前读取数据的id则证实此时的数据是在当前开启查询事务之前提交的,因而可以进行数据的查询。

图片

那么另外一个问题又来了,RC级别又是如何实现的呢?所谓RC级别,就是当别人的事务提交后,你即可以读取到别人修改后的值。因而会发生不可重复读问题。当设置为事务级别为RC时,它每次发起数据查询(set session transaction isolation level read committed;)后,每次进行数据查询都会新开启一个新的ReadView。假设当前事务中活跃着两个事务,他们的事务id分别是12、34。此时事务id为34的事务升级了数据。此时数据升级为29。同时数据对应的事务id升级为34,同时回滚指针指向上一条数据。若此时事务id为15的事务进行数据查询,此时开启readview,进行检查,发现此时的数据中对应的事务id在活跃事务id中,说明是和查询事务差不多时机执行的,但是此时的事务还未提交。因而此时的数据不可以读,所以顺着undolog版本链条读取上一次的数据。同时进行判断。假如事务B进行了提交,那么事务A再次进行数据查询的时候,会新开启一个ReadView,我们暂且称之为ReadViewA1,因为此时的事务B已经提交,所以ReadViewA1中对应的活跃列表中只有事务A对应的事务id为12。此时发现事务已提交,不再活跃事务列表中,因而可以进行数据读取。

图片

 综上分析,这就是Mysql通过ReadView以及undo log多版本链条实现RC以及RR的秘密。RC以及RR的区别就在于,RC事务隔离级别下,每次获取数据的时候,都会重新生成新的ReadView,再根据ReadView中的信心进行数据读取的判断。

三、总结

综合以上的分析我们大致理清楚了Mysql多事务并发的隔离原理,其本质是通过MVCC机制来进行实现的。而MVCC其实是基于ReadView以及undo log多版本链条实现。Mysql的默认隔离级别是RR,避免了脏读、不可重复读以及幻读的问题。
说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » Mysql神乎乎的MVCC究竟该怎样了解

发表回复