如果row的trx_id不在数组中,表明是提交的事务生成了该版本,可见
在这里还有一个特殊情况那就是对于已经删除的数据,在之前的undo log日志讲述时说了update和delete是同一种类型的undo log,同样也可以认为delete就是update的特殊情况。
当删除一条数据时会将版本链上最新的数据复制一份,然后将trx_id修改为删除时的trx_id,同时在该记录的头信息中存在一个delete flag标记,将这个标记写上true,用来表示当前记录已经删除。
在查询时按照版本链的规则查询到对应的记录,如果delete flag标记位为true,意味着数据已经被删除,则不返回数据。
如果你对这里的read-view的生成和版本链对比规则不懂,不要着急,也不要在这里浪费时间,请继续往下看,咔咔会使用一个简单的案例和一个复杂的案例给大家重现上述的规则。
六、MVCC底层原理 案例一下图是准备的素材,这里应该都理解select 返回的结果为niuniu,即事务102修改后的结果
案例一从上图中可以看到有三个事务正在进行。
事务ID为100、101是修改的其它表,只有事务ID为102修改的需要查询的这张表。
接下来看看select这一列查询返回的结果是不是就是事务ID为102修改的结果。
此时生成的read-view为[100,101],102
那么现在就可以返回去看一下read-view规则,在这里事务ID100就是min_id,事务ID102就是max_id。
这个 select语句返回结果肯定是 niuniu。
那么接下来看一下在MVCC中是如何查找数据的。
当前版本链。
此时的版本链那么就会拿着trx_id 为102进行比对,会发现这个102就是max_id
然后你再看一下版本链的对比规则中第三种情况
如果落在min_id<=trx_id<=max_id会存在俩种情况
此时信息就已经非常明确了,事务ID102是没有在数组中的,所以表示这个版本是已经提交的事务生成的,那么就是可见的呗!
毫无疑问查询会返回niuniu这个值
先通过这个简单的案例让你对版本链有一个简单的理解,接下来将使用一个比较繁琐的案例再来跟大家演示一遍。
案例二本例要求知道 select的第二个查询结果。深黑色字体。
同样是在kaka那一条记录的基础上。
案例二当事务ID100两次更新后,版本链也会改变,现在的版本链如下图,红色部分为最新数据,蓝色数据为undo log的版本链数据。
此时的版本链对于此时生成的read-view你会有什么疑问,在RR级别也就是可重复读的隔离级别下。
当在一个事务下执行查询时,所有的read-view都是沿用的第一条查询语句生成的。
那此时的read-view也就是[100,101],102
看一下底层查找步骤
目前数据的事务ID为100
根据规则会落在min_id<=trx_id<=max_id这个区间
并且当前行的事务ID100是在read-view的数组中的,表示此时事务还没有提交则不可见
继续在版本链中往下寻找,此时找到的事务ID还是100,跟上述流程一致
通过查找版本链,将发现事务 ID为102