读码农翻身之MVCC--多版本并发控制

多版本并发控制要解决的问题,其实就是基于可重复读的情况下,可以在读的时候不用加锁,也可以实现可重复读。

可重复读的流程如下所示:(小强在读取B的信息时候,需要加锁)
读码农翻身之MVCC--多版本并发控制

1、假设数据库中有一张users的表,里面有如下一行数据:
读码农翻身之MVCC--多版本并发控制
2、先给这行数据添加两个隐藏的字段:其中事务ID表明这行数据是哪个事务操作的。(事务ID是一个递增的数字,每次开始新的事务,这个数字就会增加)
读码农翻身之MVCC--多版本并发控制
3、假如旺财和小强都在操作这行数据,且分别在不同的事务中。
读码农翻身之MVCC--多版本并发控制
那么当旺财执行到上图的第一步的时候,数据是这样的:读码农翻身之MVCC--多版本并发控制
然后,创建一个叫做Read View的数据结构,有如下三个部分:
a、当前活跃的事务列表。此时存在的事务ID即【101,102】
b、Tmin,活跃事务的最小值,这里的Tmin=101
c、Tmax,是系统中最大的事务ID加上1,即Tmax=103

当进行到第二步的时候,小强执行了一个update的语句,那么此时的数据应该是这样的,此时的回滚指针指向的是上一条记录。
读码农翻身之MVCC--多版本并发控制
而此时旺财由于开启了一个事务,所以按道理说,虽然小强将age修改为了25,但是旺财应该获取到的age应该还是20,那么这个要怎么实现呢?这里有一个算法,如下所示:
读码农翻身之MVCC--多版本并发控制

那么我们根据这个算法来梳理一下:
读码农翻身之MVCC--多版本并发控制
旺财走到第一步的时候,首先这条数据的事务ID为100.则取出要读的数据行对应的数据ID,赋值给tid。那么此时tid=100.而Tmin为101,所以tid小于Tmin,那么就可以直接去读了。

当小强对数据做了修改以后,旺财第二次读的时候,tid=102,因为小强操作的事务ID为102,那么就会走到"tid在readview"这个判断分支上,而102确实是在活动事务列表中的,所以就顺着回滚指针找到下面一行记录,也就是历史记录。

那么简而言之,MVCC–多版本并发控制,其实就是不用加锁,只需要通过算法去找到正确的版本。这样读写不用互相等待,能极大提高数据库的并发能力。