写点什么

MySQL 是如何实现 RC 事务隔离级别的

  • 2022 年 2 月 17 日
  • 本文字数:985 字

    阅读完需:约 3 分钟

本文分享自华为云社区《MySQL RC事务隔离级别的实现》,作者: JavaEdge 。


Read Committed,事务运行期间,只要别的事务修改数据并提交,即可读到人家修改的数据,所以会有不可重复读、幻读问题。


ReadView 机制基于 undo log 版本链条实现的一套读视图机制,事务生成一个 ReadView:

  • 若为事务自己更新的数据,自己可以读到

  • 或在你生成 ReadView 之前提交的事务所修改的值,也可读到

  • 但若你生成 ReadView 时,就已经活跃的事务,但如果它在你生成 ReadView 之后修改的数据并提交了,此时你读不到

  • 或你生成 ReadView 以后再开启的事务修改了数据,还提交了,也读不到


所以上面那套机制就是 ReadView 的一个原理如何基于 ReadView 实现 RC?核心设计:当一个事务设置 RC,他是每次发起查询,都重新生成一个 ReadView!


数据库里有一行数据,是事务 id=50 的一个事务,很久以前就插入的,当前活跃事务:

  • 事务 A(id=60)

  • 事务 B(id=70)


现在事务 B 发起 update,更新这条数据为 b,所以此时数据的 trx_id 会变为事务 B 的 id=70,同时生成一条 undo log:


这时,事务 A 要发起一次查询操作,就会生成一个 ReadView。



这时事务 A 发起查询,发现当前这条数据的 trx_id=70。即属于 ReadView 的事务 id 范围之间,说明是他生成 ReadView 之前就有这个活跃的事务,是这个事务修改了这条数据的值,但此时事务 B 还没提交,所以 ReadView 的 m_ids 活跃事务列表里,有[60, 70]两个 id,此时根据 ReadView 机制,事务 A 无法查到事务 B 修改的值 b。


接着就顺着 undo log 版本链条往下查找,就会找到一个原始值,发现其 trx_id 是 50,小于当前 ReadView 里的 min_trx_id,说明是他生成 ReadView 之前,就有一个事务插入了这个值并且早就提交了,因此可以查到这个原始值。


接着,假设事务 B 提交,提交了就说明事务 B 不会活跃于数据库里了。事务 A 下次再查询,就可以读到事务 B 修改过的值了。那到底是怎么让事务 A 能够读到提交的事务 B 修改过的值呢?


让事务 A 下次发起查询,再生成一个 ReadView,数据库内活跃的事务只有事务 A,因此:

  • min_trx_id 是 60

  • mac_trx_id 是 71

  • m_ids=60,事务 B 的 id=70 不会出现在 m_ids 活跃事务列表


此时事务 A 再次基于这个 ReadView 去查询,会发现这条数据的 trx_id=70,虽然在 ReadView 的 min_trx_id 和 max_trx_id 范围之间,但是此时并不在 m_ids 列表内,说明事务 B 在生成本次 ReadView 之前就已提交。说明这次你查询就可以查到事务 B 修改过的这个值了, 此时事务 A 就会查到值 B。


点击关注,第一时间了解华为云新鲜技术~

发布于: 刚刚阅读数: 2
用户头像

提供全面深入的云计算技术干货 2020.07.14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
MySQL 是如何实现RC事务隔离级别的