MySQL之MVCC如何实现可重复读和提交读

(/≧▽≦)/~┴┴ 嗨~我叫小奥 ✨✨✨

👀👀👀 个人博客:小奥的博客

👍👍👍:个人CSDN

⭐️⭐️⭐️:Github传送门

🍹 本人24应届生一枚,技术和水平有限,如果文章中有不正确的内容,欢迎多多指正!

📜 欢迎点赞收藏关注哟! ❤️

文章目录

如何实现可重复读

今天来带大家学习一下,MVCC是如何实现可重复读的。

假设事务A和事务B同时堆主键id = 1的记录进行操作,事务A和B的事务id分别为20和30 。

那么这两个事务就会创建各自的ReadView:

此时事务A的creator_trx_id = 20,事务B的creator_trx_id = 30。由于仅有两个活跃的事务,所以事务列表中最小的事务是事务A,所以min_trx_id = 20,下一个也就是最大的事务id的max_trx_id值应该为事务B的下一个id,即max_trx_id = 31 。

事务A去读取主键id为1的数据,找到记录之后就会查看该记录的trx_id,假设事务A查询到该记录的trx_id为10 。

随后和自己的creator_trx_id进行比较:

发现主键id = 1的记录 trx_id = 10 < A.creator_trx_id = 20,就判断到该记录的事务id不存在于活跃的事务列表中小于自己的事务id,这代表本次记录的值是在自己查询之前提交的,所以可以读取,并且在读取完之后,将该记录的trx_id修改为自己的事务id。

然后,把age字段的值从28修改为30 。

另外,被修改的字段还有Undo Log中的另一个隐藏字段:roll_pointer指针。它会去指向被事务A修改的之前的数据版本,也就是fancy的年龄为28的数据的地址,就是为了用来记录,方便下次被查询。

随后,事务B也对该条数据进行操作,事务B的要求是将fancy的年龄从30直接修改为50 。

此时会再次进行一次trx_id的比较过程,去判断自己的creator_trx_id是否大于这条记录对应的trx_id,如果大于,就去修改这条记录的值,将年龄从30修改为50:

并且Undo Log版本链也会更新对应的数据。

重点来了

如果此时事务A再去读取主键id = 1这条记录,发现这条记录的trx_id已经被修改为了30,再次进行事务id之间的区间比较:发现 A.trx_id = 20 < 主键 id = 1 记录.trx _id = 30 < max_trx_id = 31,并且trx_id = 30 存在于活跃事务集合m_ids中,就代表自己读取到的是和自己同一时间范围内一块启动的另一个未提交的活跃事务所修改的值。

那么此时事务A是不会去读取这条记录对应的数据的,它会通过Undo Log版本链上的roll_pointer指向的地址去查找上一个旧版本的记录,直到找到第一条trx_id小于等于自己的事务id并且不存在于活跃事务id集合m_ids列表中的记录,代表是别的事务已经提交的最后一条记录然后读取它。

这样的话,每一个事务去读取或者修改同一个记录时,只能操作已经提交的数据,未提交的数据时不能被读取到的,MySQL就这样实现了可重复读。

其实本质上就是通过Read View的字段判断这行记录是否对自己可见,如果不可见的话再去找Undo Log里面的记录,直到找到对自己可见的数据,然后才能进行操作。

如何实现提交读

提交读能够解决脏读,脏读问题其实本质上就是一个事务读取到了另一个事务没有提交的内容。

下面我们来学习一下MVCC是如何实现提交读的。

假设事务A和事务B同一时刻启动,事务B将同一行的记录,也就是fancy的年龄改成了25,但是事务B并没有提交,此时事务A就会去读取这条记录的trx_id。

事务A查看到该记录的trx_id居然比事务A的Read View列表中的creator_trx_id值大,并且修改这条记录的事务trx_id存在于自己的m_ids列表里面,那么事务A就可以判断到该记录是被另一条没有提交的事务修改的,所以它不会去读取这条数据的内容 ,事务A会通过Undo Log版本链继续找第一条trx_id 小于等于自己的事务id并且不在m_ids列表里面的数据。

所以,事务A不会看到事务B正在修改的数据,脏数据也不会产生。

总结

InnoDB 中,MVCC 就是通过 Undo Log + Read View 进行数据读取,Undo Log 保存了历史快照,而 Read View 规则帮我们判断当前版本的数据是否可见。从而不需要通过加锁的方式,就可以实现提交读和可重复读这两种隔离级别。

总的来说,MVCC本质上就是一种数据结构。已提交读和可重复读都是使用了Read View这种策略通过区间判断获取自己能够读取的内容,然后展示。InnoDB通过MVCC,解决了脏读、不可重复读。

相关推荐
阳光九叶草LXGZXJ4 小时前
达梦数据库-报错-15-列【XXX】长度超出定义
linux·运维·数据库·sql·学习
字节渡客5 小时前
Redis键明明过期了,业务还在读到旧数据
数据库·redis·spring
OnlineProxy7 小时前
亚马逊多账号运营:如何在规避“关联封号”风险的同时实现电商规模化扩张
服务器·数据库·redis
辻弋2018 小时前
五年前的旅行视频糊成马赛克?Video2X用Real-ESRGAN逐帧重建细节,但只支持Windows、集显用户建议直接放弃
服务器·数据库·windows·游戏引擎·电脑
可乐鸡翅yeah_9 小时前
业务中 M3U8 水印相关坑,硬水印和动态水印区别
前端·网络·数据库·ffmpeg·m3u8在线
石头麻辣鱼10 小时前
Bamboo 调度系统 OceanBase 适配实战:存储过程迁移踩过的三个大坑
数据库
龙亘川10 小时前
数智驱动民政升级 精准守护民生保障
大数据·数据库·人工智能
念何架构之路10 小时前
zap扩展生态与总结
java·前端·数据库
晚安日记wanna11 小时前
MySQL 回表为什么这么慢?5 种优化手段逐个拆解
数据库·mysql·性能优化
第七页独白11 小时前
汽车零件厂如何通过 QMS 真正落地 IATF 16949——QMS软件系统:品质检验-内审稽核-8d客诉管理:全星质量管理软件系统
java·前端·数据库