mvcc版本链角度剖析

1.例题假设:

假设同一条记录,事务id为80已提交,其他均未提交
在这里插入图片描述
每个事务都有一个事务id,对同一条记录的修改如上图对id=1的记录的修改会将最近的修改插到版本链后面,每个事务都能查到自己修改的那条记录的最新版本(改了多次能查到最近的一次),因为版本链上同一条记录的不同版本有对应事务id字段值,标明是哪个事务的修改。如上图80,81,82,200都是事务id字段值,意味着事务id为80的事务能查到事务id字段值为80的那条记录…以此类推。

2.mvvc如何保证读已提交?

触发条件:事务第一次读取某条记录
当有一个事务id为100的事务到时,我们希望的是读已提交,也就是能读到事务id字段值为80的那条最初版本的已提交的记录,根据上面提到的不管本事务有没有提交,每个事务都能查到自己修改的那条记录的最新版本(改了多次能查到最近的一次),那么如果自己没有有修改事务,仅仅是查看,怎么查到已提交的最新版本呢?这就引入了readview。
readview有个参数m_ids,m_ids:[活跃事务id1,活跃事务id2,活跃事务id3…],活跃事务就是未提交的事务,上图例子中的m_ids:[81,82,200,300],当你想读已提交事务的时候,比如select * from test where id=1时,就会拿着m_ids:[81,82,200,300]去版本链中找事务id字段值不在m_ids:[81,82,200,300]的那个版本的记录,也就是我们期望的id字段值为80的那条最初版本的已提交的记录。

3.mvvc如何保证可重复读?

如上面中事务id为100的事务第一次select读到已提交的记录(即事务id字段值为80的那条最初版本的已提交的记录),当这个事务再次读取同一条记录时,我们期望读到的版本是第一次读取的那个版本,因此即使在这个记录后来生成了不同版本的时候,就算提交了,事务id为100的事务再次select的时候也不会再生成m_ids,而是使用第一次生成的m_ids:[81,82,200]去对比,因此也能拿到第一次select的那个版本(如果是读已提交级别的话就会生成m_ids:[81,82],比如说事务id为200的事务提交了,那么就会取出事务id字段值为200的那个版本的已提交的记录)。

思考?如果后来出现了一个没有在版本链上出现过的事务(事务id为400)怎么办呢,由于不可重复读只用第一次select生成的resdview的m_ids,那么通过m_ids:[81,82,200]也能拿到事务id为400修改的记录的版本,不管它提不提交。
解答:
如果被访问版本的trx_id属性值大于或等于ReadView中的max_trx_id值,表明生成该版本的事务在当前事务生成ReadView后才开启,所以该版本不可以被当前事务访问。

解析:
m_ids:[81,82,200]中max_trx_id值为301(没有回滚的情况下),被访问版本的trx_id=400,trx_id>max_trx_id,所以不会被访问到,保证了可重复读。

提示:

  • max_trx_id并不是m_ids中的最大值,事务id是递增分配的。比方说现在有id为1,2,3这三个事务,之后id为3的事务提交了。那么一个新的读事务在生成ReadView时,m_ids就包括1和2,min_trx_id的值就是1,max_trx_id的值就是4。
  • creator_trx_id:表示生成该ReadView的事务的事务id。只有在对表中的记录做改动时(执行INSERT、DELETE、UPDATE这些语句时)才会为事务分配事务id,否则在一个只读事务中的事务id值都默认为0。

4.细节要点:

  • 一个事务在select生成ReadView之前时,如果该事务对该记录做了改动有了事务id,后来在生成生成ReadView时会将自己的事务id加入m_ids,原因是自己也没有提交。
  • 自己的修改优于可重复读。比如同一个事务查询同一条记录,再修改同一条记录,最后再查询同一条记录,查到的是修改后的,不再遵循可重复读。
  • 读已提交最新提交的事务就会把对应的版本调整到版本链尾部,查找时从尾部找起。
    参考文章
    参考文章
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fire king

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值