MVCC总结

下面内容是参考文章末尾博客做的一点总结,博客中讲解的很好,但是对其中一些说法不是很赞同,所以下面只整理认同的部分。

多版本控制

指的是一种提高并发的技术。最早的数据库系统,只有读读之间可以并发,读写,写读,写写都要阻塞。引入多版本之后,只有写写之间相互阻塞,其他三种操作都可以并行,这样大幅度提高了InnoDB的并发度。

ReadView

事务快照是用来存储数据库的事务运行情况。一个事务快照的创建过程可以概括为:

  1. 查看当前所有的未提交并活跃的事务,存储在数组中
  2. 选取未提交并活跃的事务中最小的XID,记录在快照的xmin中
  3. 选取所有已提交事务中最大的XID,加1后记录在xmax中

这里暂时不知道ReadView中是否包含当前事务,如果包含当前事务,那么根据下面的可见性算法,事务对记录进行变更后在事务内不能可见。

RR隔离级别下,ReadView是在事务中第一次select的读操作时创建。RC隔离级别下,在事务中每一次select都会创建ReadView。

Undo log

当对记录进行变更时就会产生Undo记录,Undo记录分为两个种Insert Undo log和Update Undo log。Insert Undo log记录事务的insert操作,只用于事务回滚,事务提交后就可以删除。Update Undo log记录事务的update和delete操作,不仅事务回滚需要,在读取时也需要,所以不能随便删除,只有当ReadView中没有关联到当前Undo log时,才可以被删除。

DB_TRX_ID、DB_ROLL_PTR、DB_ROW_ID

这三个字段是InnoDB添加的隐藏字段,DB_TRX_ID表示最后一次变更该条记录的事务,DB_ROLL_PTR表示回滚指针指向该记录上一个版本,DB_ROW_ID表示默认的聚簇索引(这里不考虑)

Undo链

每次记录更新时,都会保存上一个版本,Undo链就是维持这些版本关系的模型。例如,当更新一条记录时,会对这个记录加锁,将改行记录修添加到Undo log,将Undo log位置记录到DB_ROLL_PTR 最后修改记录值,将事务id记录到DB_TRX_ID。每次更新记录就保存一个Undo log,这样就构成了可以找到旧版本的Undo链。

可见性算法

创建ReadView, ReadView中最小的事务id为up_limit_id,最大的事务id为low_limit_id

  1. 记录的DB_TRX_ID小于up_limit_id,记录由之前已经提交的事务变更,记录对当前事务可见
  2. 记录的DB_TRX_ID大于low_limit_id,记录由新开启的事务变更,当前事务不能确定新事务是否提交,所以记录对当前事务不可见。
  3. 记录的DB_TRX_ID介于up_limit_id和low_limit_id之间,遍历ReadView如果不包含DB_TRX_ID则说明变更该条记录的事务已提交,记录对当前事务可见。否则,记录不可见,查找Undo链中可见的记录。

MVCC如何实现读已提交和可重复读

  1. RC隔离级别下每次select时创建一个ReadView(假设不包含当前事务),根据可见性算法,只有DB_TRX_ID小于low_limit_id并且DB_TRX_ID不在ReadView中时,也就是DB_TRX_ID对应的事务已经提交。所以记录一定是由已提交事务变更。
  2. RR隔离级别下,因为ReadView不变,根据可见性算法计算得到的结果也不变,所以每次select得到的记录都应该是一样的。

MVCC和幻读

幻读是指用同样的条件查询或更新,前后的影响的记录数量不同

  1. 在RR隔离级别下,根据上面MVCC实现可重复读,可以发现对于select来说,MVCC已经保证不会出现幻读
  2. 如果对记录进行更新则需要对记录加锁,InnoDB的加锁策略(gap lock)会保证不产生幻读

 

参考:

https://segmentfault.com/a/1190000012650596?utm_source=tag-newest

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值