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

2022年05月11日 阅读数:2
这篇文章主要向大家介绍MySQL 是如何实现RC事务隔离级别的,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。
摘要:Read Committed,事务运行期间,只要别的事务修改数据并提交,便可读到人家修改的数据,因此会有不可重复读、幻读问题。

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

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

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

  • 若为事务本身更新的数据,本身能够读到
  • 或在你生成ReadView以前提交的事务所修改的值,也可读到
  • 但若你生成ReadView时,就已经活跃的事务,但若是它在你生成ReadView以后修改的数据并提交了,此时你读不到
  • 或你生成ReadView之后再开启的事务修改了数据,还提交了,也读不到

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

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

  • 事务A(id=60)
  • 事务B(id=70)

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

这时,事务A要发起一次查询操做,就会生成一个ReadViewget

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

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

接着,假设事务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。

 

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