MVCC如何基于readView实现读并提交和可重复读

readView是快照读SQL执行时MVCC提取数据的依据,快照读不一定读的是最新的版本,也有可能是历史版本,所以readView的作用就是在执行查询语句时,判断应该返回哪个版本,readView记录并维护系统当前活跃的事务(未提交的)id readView主要包含下面几个部分

m_ids:当前有哪些事务正在执行,且还没有提交,这些事务的id就会存在这里
min_trx_id:指m_ids里的最小值
max_trx_id:指下一个要生成的事务id,下一个要生成的事务id肯定比现在所有的事务id都要大
creator_trx_id:创建视图的事务的id

读并提交

首先先看一张表 接下来有两个事务更新了表数据

那么对应的版本链就会变成

假设现在事务0来进行查询语句,创建视图 然后看下readView中的参数分别都是什么值

m_ids(当前正在执行但是还没有提交的事务ID):20 60 min_trx_id:20 max_trx_id=61 creator_trx_id=0

接下来我们将这些版本与这些参数进行比较,只要符合其中一个条件都可以读到

rx_id==creator_trx_id,执行一次快照读,就会生成一个readView,事务5执行了快照读,所以creator_trx_id=trx_id=5,可以访问该版本
trx_id<min_trx_id:表明trx_id事务在生成readView前已经提交,所以该版本也可以被当前事务访问
trx_id>max_trx_id:表明生成该版本的事务id在生成readView后才生成,该版本不可被当前事务访问
min_trx_id<=trx_id<=max_trx_id:比如此时的m_ids为[5,6,7,9,10], 若trx_id是6,说明创建ReadView时生成该版本的事务还是活跃的,该版本不可被访问 若trx_id是8,说明创建ReadView时生成的该版本的事务已经被提交,该版本不可被访问

最后一列是因为20在m_ids中,所以不可访问 所以综上判断,此时如果进行快照读的话,读到的数据还是最开始没有被修改的数据,所以就是必须要提交事务之后才能看提交之后的数据,

可重复读

RC和RR生成ReadView的时机不同

RC:在事务中每一次执行快照读时就会生成ReadView,所以如果在一个事务中,执行了两次select语句,就会生成两次readView,就那上边的例子来说,第一次select的时候,读到的是张三,没有读到王五这条数据,是因为它还没有提交,如果在这个时候将它commit一下,再select之后,读到的数据就是王五了,第一次读到的是张三,第二次读到的是王五,这样就是两个不同的结果了,就出现了不可重复读的问题
RR:仅在事务中第一次执行快照读时生成ReadView,后续复用这个ReadView,也就是一个事务只会生成一个readView
经验分享 程序员 微信小程序 职场和发展