刷题刷出新高度,偷偷领先!偷偷领先!偷偷领先! 关注我们,悄悄成为最优秀的自己!
mvcc作为多版本并发控制,使用undo log实现,同样也可以实现上述四种隔离级别,只不过实现手段不是通过传统意义上的锁罢了。当然针对RU(读未提交)隔离级别,所有更改的语句别的事务都可以直接看到,那根本没有保留多个版本的必要,用到的就是最新的唯一版本,同样S(序列化)级别,排队一个个去读写,也根本没有保留多个版本数据的必要,因为都是用最新的数据就行了。
1)官方一点的解释:并发访问(读或写)数据库时,对正在事务内处理的数据做 多版本的管理。以达到用来避免写操作的堵塞,从而引发读操作的并发问题。
2)无节操解释,拿厕所的纸巾举例子,为了让不同的人多次进来看到的纸巾都是一样的,那么每次有人用纸巾,先做个标记版本A,(A能看到的),然后放在一个柜子里,然后复制一个一模一样的纸巾放在纸巾盒里,标记成当前版本(自己看到的)。然后假定做一个看的规则,每个人进来只能根据规则看到之前看到的那卷纸巾,保证每个人多次进来看到的纸巾是一致的,好吧,纸巾真多,够麻烦!后面在详细解释
数据表增加两个隐藏列DATA_TRX_ID和DATA_ROLL_PTR,用于实现mvcc
事务 A 对值 x 进行更新之后,该行即产生一个新版本和旧版本。假设之前插入该行的事务 ID 为 100,事务 A 的 ID 为 200。操作过程如下
上文中的undo log是一个链表结构,也就是如果多个事务都修改了这行数据,会根据事务ID的先后,以链表形式存放,至于旧版本存放在链表的先后顺序,这个其实无关紧要,只要方便获取就好,我倾向于每次修改后把旧版放在链表的头部,这样可以保证从指针递归下来,先找到较新的数据,再找到更旧的数据,一个个版本去判断是否是自己可以看到的版本。
当前事务读取数据的时候如何判断应该读取哪个版本?mysql中引入了一个可读试图ReadView的概念。
ReadView主要包含如下属性:
ReadView有了上面4个属性后,那么应该以什么样的规则,判断当前事务到底可以读取哪个版本的数据呢?
通俗点来说,也就是ReadView中通过最大事务ID,mIds最小事务ID,mIds活跃事务列表,将当前要读的数据的事务ID分成了3种情况:
当一个事务要读取一行数据,首先用上面规则判断数据的最新版本也就是那行记录,如果发现可以访问就直接读取了,如果发现不能访问,就通过DATA_ROLL_PTR指针找到undo log,递归往下去找每个版本,直到读取到自己可以读取的版本为止,如果读取不到那就返回空。
本文链接:说说mvcc 与 undo log
版权声明:本站点所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明文章出处。让学习像火箭一样快速,微信扫码,获取考试解析、体验刷题服务,开启你的学习加速器!