(笔记总结自b站马士兵教育课程)
本文主要分析readview的案例。
一、简介
readview:表示事务进行快照读操作的时候产生的读视图,在该事务进行快照读的那一刻会生成一个系统当前的快照,但是此时的快照不是数据的快照,而是事务相关信息的快照。
trx_list | readview生成时刻当前系统活跃的事务id |
up_limit_id | 活跃列表中事务id最小的值 |
low_limit_id | 系统尚未分配的下一个事务的id |
二、基本案例
首先介绍可见性算法:
①首先比较DB_TRX_ID<up_limit_id,如果小于,则当前事务能看到DB_TRX_ID所在的记录,如果大于等于进入下一个判断。
②接下来判断DB_TRX_ID>=low_limit_id,如果大于等于则代表DB_TRX_ID所在的记录在readview生成后才出现的,那么对于当前事务肯定不可见,如果小于,则进入下一步判断。
③判断DB_TRX_ID是否在活跃事务中,如果在,则代表在readview生成时刻,这个事务还是活跃状态,还没有commit,修改的数据,当前事务也是看不到,如果不在,则说明这个事务在readview生成之前就已经开始commit,那么修改的结果也是能够看到的。
基本案例分析:
时刻 | 事务1 | 事务2 | 事务3 |
t1 | begin; | begin; | begin; |
t2 | update; commit; |
||
t3 | select; |
针对t3时刻事务1的select操作的readview快照:
trx_list | 1,3 |
up_limit_id | 1 |
low_limit_id | 4 |
DB_TRX_ID | 2 |
我们对此案例进行可见性算法分析:
①因为DB_TRX_ID>up_limit_id,所以进入下一步判断。
②因为DB_TRX_ID<low_limit_id,所以进入下一步判断。
③DB_TRX_ID不在trx_list活跃事务中,所以可读。
综上,事务1的select操作可以读到更新之后的结果值。
三、综合案例
时刻 | 事务1 | 事务2 | 事务3 |
t1 | begin; | begin; | begin; |
t2 | *select; | select; |
|
t3 | update; commit; |
||
t4 | **select; |
我们首先分析*select的readview快照:
trx_list | 1,2,3 |
up_limit_id | 1 |
low_limit_id | 4 |
DB_TRX_ID | 0 |
可见性算法分析结果:可读。
我们再分析 **select的readview快照:
trx_list | 1,3 |
up_limit_id | 1 |
low_limit_id | 4 |
DB_TRX_ID | 2 |
可见性算法分析结果:可读。
但是实验结果是不可读的,其实这里**select沿用了上一次的*select产生的readview快照,但是DB_TRX_ID是新生成的:
trx_list | 1,2,3 |
up_limit_id | 1 |
low_limit_id | 4 |
DB_TRX_ID | 2 |
可见性算法分析结果:不可读。这样就和实验结果一致了。
四、关于隔离级别
不可重复读:在同一个事务中,两次相同的操作读取的数据是不一样的。
RC:读已提交。
RR:重复读。
在RC隔离级别的时候,每一次进行快照读都会生成新的readview。上述案例我们可以发现存在不可重复读的问题。
在RR隔离级别的时候,只有在第一次进行快照读的时候才会生成readview,之后的快照读都会沿用之前的readview,不会重新生成。上述案例我们可以发现解决了不可重复读的问题。文章来源:https://www.toymoban.com/news/detail-718635.html
两个隔离级别的区别点在于生成readview的时机不同。文章来源地址https://www.toymoban.com/news/detail-718635.html
到了这里,关于MVCC:多版本并发控制案例分析(二)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!