本文主要是介绍这下弄懂什么是快照读和什么是当前读了,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
锁模块之快照读和当前读
InnoDB可重复读隔离级别下如何避免幻读?
- 表象:快照读(非阻塞读) --伪MVCC
- 内在:next-key锁(行锁+gap锁)
回答这个问题前我们先要了解下什么是快照读、什么是当前读。
当前读:select...lock in share mode; select...for update;
当前读:update、insert、delete
快照读:不加锁的非阻塞读,select
演示一下什么是快照读、什么是当前读
打开两个会话,确保一下两个会话的事务隔离级别都在RR级别下
快照读读到的版本数据取决于快照读先出现的地方的时机,我们来看下开启事务后先不执行快照读直接进行更新操作
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FKSOFBQO-1594698883837)(C:\Users\14222\AppData\Roaming\Typora\typora-user-images\image-20200714095058653.png)]
以上演示的是RR级别下的快照读和当前读,快照读的版本取决于快照读发生的时机。而在RC级别下,快照读读取的是当前最新的数据。
RC、RR级别下的InnoDB的非阻塞读如何实现
我们在存储一条数据时,除了我们能看到的字段,其实mysql还给我们添加了许多的隐藏字段,比如与我们题目有关的字段:DB_TRX_ID、DB_ROLL_PTR、DB_ROW_ID字段,看他们的名字就能够大致知道是什么意思。
- DB_TRX_ID:事务ID,每开启一个新事务,当前的事务id就自动加一,事务id越大,表明当前启动事务时间离当前时间越近。
- DB_ROLL_PTR:回滚指针,比如当前事务去更新一条数据的时候,这条数据的回滚指针会指向undo log里最大的事务id的地址,也就是最新的undo日志
- undo log是在一个事务中每进行一次增删改操作就形成的一条undo日志,它是用于在事务回滚是回到事务开启之前的版本。它也分为insert undo log和update undo log
- DB_ROW_ID:行号,新行插入,对应行号,如果一个InnoDB表中的字段没有唯一索引和主键索引,InnoDB会自动生成隐藏自增主键字段,也就是这个字段。
实现快照读除了用到上面的三个隐藏字段和undo日志,还需要一个read view,当我们去执行快照读的时候,针对我们读的数据会创建一个read view来决定我们读到的是哪个版本的数据,有可能是最新版本的数据,也有可能是undo日志里的某个版本的数据。read view遵循一个可见性算法,主要是将要修改的数据的DB_TRX_ID取出来与系统其它活跃事务ID作比较,如果大于等于这些ID,就通过DB_ROLL_PTR指针去取出undolog中的数据直到小于这些活跃事务ID为止,这样就能保证获取到的数据是当前事务可见的最稳定的版本。
在RR级别下,session在开启事务后的第一条快照读会创建一个快照,也就是read view,将当前系统中活跃的其他事务记录起来,此后,再调用这个read view,在RC级别下,在开启事务后每次调用快照读的情况下都会创建一个快照,这就是之前RC级别下快照读每次都能看到其他事务进行的最新的增删改,而在RR级别下如果首次使用快照读是在别的事务进行增删改之前调用的,此后即便别的事务做了增删改还是得不到最新数据的原因。所以在RR级别下,首次进行快照读的时机是很重要的。
为什么是伪MVCC
MVCC就是多版本并发控制,也就是非阻塞读,上面提到的MVCC为什么是伪MVCC呢?因为这里的undo log是串行化的不属于多个版本共存的例子,所以不是MVCC。
这篇关于这下弄懂什么是快照读和什么是当前读了的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!