MVCC多版本并发控制机制

MVCC多版本并发控制机制

MySQL在可重复读级别下如何保证较高的隔离性,同样的SQL语句在一个事务里多次执行查询结果,就算其他事务对数据有修改也不会影响当前事务SQL语句的查询结果;

Undo日志版本链

Undo日志版本链是指一行数据被多个失误依次修改过后,在在这个事务修改完后,MySQL会保留修改前的数据到undo回滚日志,并且用两个隐藏字段事务ID(trx_id)和回滚指针(roll_pointer)把这些undo日志串联起来形成一个历史版本链。

在这里插入图片描述

  1. 修改前把记录放入undo日志里。
  2. 修改后的记录会有一个事务ID,以及回滚指针,该指针指向1步骤里的undo日志记录的主键ID;

Read View读视图

在可重复读隔离级别下,当事务开启时,执行任何查询SQL时,会生成当前事务事务的一致性读视图(ReadView),该视图在事务结束之前都不会变化,这个事务有执行查询时所有未提交事务的ID数组(数组里面最小的ID为min_id)和已创建的最大事物ID(max_id),事务里的任何SQL查询结果需要从对应undo日志版本链里的最新数据开始逐条跟read-view做对比,从而得到最终的快照结果;

版本链比对规则

在这里插入图片描述

1. 如果row的trx_id落在绿色部分(trx<min_id),表示这个版本是已提交的事务生成的,这个数据是可见的;
2. 如果row的trx_id落在红色部分(trx_id>max_id),表示这个版本是由将来启动的事务生成的,是不可见的 (若 row 的 trx_id 就是当前自己的事务是可见的);
3. 如果row的trx_id落在黄色部分(min_id<trx_id<=max_id),那就包括两种情况:
- 若row的trx_id在视图数组中,表示这个版本是还没提交的事务生成的,是不可见的 (若 row 的 trx_id 就是当前自 己的事务是可见的);
- 若row的trx_id不在视图数组里,表示这个版本是已经提交了的事务生成的,可见。

begin/start transaction命令不是一个事务的起点,在执行到它们的第一个修改操作InnoDB表的语句,事务才真正启动,才会向MySQL申请事务ID,MySQL内部是严格按照事务启动顺序分配事务ID的。

delete

对于删除情况可以认为是update的特殊情况,会将版本链上最新的数据复制一份,然后将trx_id修改成删除操作的trx_id,同时在该条记录的头信息(record header)里的标记位(delete flag)写上true,表示当前记录已经被删除,在查询时按照上面的规则查询对应的记录,如果删除标记位为true,一位着记录已经被删除,则不返回数据。

疑问

为什么未提交的事务min_id可以划分绿色和橙色部分?难道绿色部分的事务ID都会小于min_id吗?

Undo日志版本链中,每行记录的事务ID是自增的,因此可以使用min_id来划分绿色和橙色区域,绿色部分是都已经提交了的。

例如未提交的事务ID有5,10,29,32,min_id就是5,6前面的事务都是已经提交了的。

总结

MVCC机制的实现就是通过read-view机制与undo版本链比对机制,使得不同的事务会根据数据版本链对比规则读取 同一条数据在版本链上的不同版本数据。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值