ReadView 是 InnoDB 中一个至关重要的概念,他是实现MVCC的基础,同时他也是支持不同的事务隔离级别的基础。,同时提高系统的并发能力和性能。
他到底是干啥的?简单来说,其实就是一句话:Read View 主要来帮我们解决可见性的问题的, 即他会来告诉我们本次事务应该看到哪个快照,不应该看到哪个快照**。
快照?
我们都知道,MySQL中用不同的事务隔离级别,比如我们常见的RR和RC,RR要求在一个事务中,多次读取的结果是保持一致的,而RC则要求每次都要读取到最新的值。
那么,具体如何实现的RR和RC的读数据的时候的不同现象,就是这个快照。
在可重复读(Repeatable Read)级别下,快照(ReadView)在事务开始时创建一次,并在整个事务期间保持不变。
在读已提交(Read Committed)级别下,快照(ReadView)会在每次查询时重新创建,以反映数据库中的最新提交更改。
ReadView的定义在MySQL的不同版本中不一样,拿MySQL 5.7 (8.0也一样)举例,ReadView定义如下
这几个东西是干嘛的,有啥用,代表了啥?其实,在5.6(https://github.com/zhujzhuo/MySQL-5.6/blob/mysql-5.6.11/storage/innobase/include/read0read.h ) 中的ReadView的定义更加直观:
也就是说,在 Read View 中有几个重要的属性:
trxids中包含了lowlimitid和uplimitid的信息,其实trx_ids = [up_limit_id,low_limit_id)
(但是需要注意,他并不一定连续,只是会包含uplimitid,并且小于lowlimitid,比如他可能是5,7,8,11) ,并且你没看错,uplimitid就是表示最低水位,lowlimit_id就是表示最高水位,至于为啥这么叫,我也不知道。。。
网上还有些资料这里有mintrxid、maxtrxid、mids等的说法,我翻了下源码5.6、5.7、8.0,并没有找到出处。就先不纠结了,以源码为准。
目前看到有关于maxtrx_id的定义,但是是用在二级索引的MVCC支持中的。
也就是说,每一次读取数据的时候(RC情况下),都会生成一个ReadView,并且在其中记录上trxids(包含了[uplimitid,lowlimitid))和creatortrx_id。
那么,一个事务应该看到哪些快照,不应该看到哪些快照该如何判断呢?
假如一个ReadView的内容为:
trx_ids = [5,6,8)
low_limit_id = 8
up_limit_id = 5
creator_trx_id = 7
假设当前事务要读取某一个记录行,该记录行的 dbtrxid(即最新修改该行的事务ID)为 trx_id,那么,就有以下几种情况了:
1、trxid< uplimit_id,即小于5的事务,说明这些事务在生成ReadView之前就已经提交了,那么该事务的结果就是可见的。
2、trxid>lowlimit_id,即大于8的事务,说明该事务在生成 ReadView 后才生成,所以该事务的结果就是不可见的。
3、uplimitid
总结一下就是,一个事务,能看到的是在他开始之前就已经提交的事务的结果,而未提交的结果都是不可见的。
那不可见的话,怎么办呢?这时候就需要用到undolog了。