mvcc机制即多版本并发控制
当在事务中使用了写操作(增删改)语句时会给当前事务生成一个事务id,事务id是递增的
同时,对于被修改的行的数据会创建一个数据版本 ,这个数据版本除了包含原有的字段还会包含一个事务id和一个回滚指针
接下来通过几条sql语句来讲解mvcc机制:
首先假设这里有一个account表,此时里面只有一条数据
trx_id:事务id
roll_pointer:回滚指针
假设上面的4个事务都已经开启了,现在执行3行和4行,由于是写操作,所以会生成一个事务id,这里我们假设是110 和 120,注意此处操作的不是account表,只是为了生成事务id。
接下来执行第5行,同样是一个写操作也会生成事务id,同时上面我们说过,对于被修改的数据行还会生成一个数据版本,于是这个新生成的数据版本就是当前数据行最新的版本,它的回滚指针会指向上一个版本:
紧接着事务130就提交了,然后另一个事务指向了一个查询语句,这里大家应该都知道结果是ting130,因为事务130提交了。注意查询语句不会生成事务id
此时继续往下执行,8和9行,同样是更新语句所以也会生成数据版本,注意每个事务中只有第一次执行写操作语句时会生成事务id。
此时第10行执行一个查询语句,我们分析一下此时的查询结果是什么:
当事务中第一次执行查询操作时,会生成一致性视图 read -view,也可以称为快照,他由当前未提交事务id组成的数组和已创建的最大事务id(max_id)组成,其中未提交事务id中最小的id我们称为min_id,通过min_id和max_id可以把事务分为三个部分:
由于min_id是所有未提交事务中最小的id,所以事务id小于min_id的一定是已经提交的事务是可见的,同时大于max_id的事务,是生成快照时还没有创建的事务,是不可见的,在min_id和max_id之间的事务要分两种情况,在未提交数组中则说明是不可见的,不在则说明事务已经提交是可见的,当执行查询语句,就会沿着版本链从最新的数据开始查,直到查到可见的数据。
所以第7行时,第四个事务就已经生成了快照,当时只有事务130提交了,所以生成的read_view是:[ 110 , 120 ] 130 ,110即为min_id,130为max_id,由于同一个事务中只有第一次使用查询语句时会生成read_view,所以此时第10行的查询语句会沿用上次的read_view即 [ 110 , 120 ] 130
此时我们沿着版本链去查数据,首先查到的是ting112,发现事务id在未提交事务数组中说明不可见,沿着回滚指针往下找到ting111发现同样不可见,继续往下找到ting130,事务id为130 ,130 小于等于max_id并且不在未提交事务数组中,是可见的,于是返回ting130。
接下来继续往下执行,到第14行的时候,又将执行一条查询语句,可以先不看下面自己试着梳理一下返回什么。
此时版本链中又多了两条数据:
我们同样按照read_view在版本链中找,注意,这里不会生成新的read_view会沿用上次生成的
[ 110 , 120 ] 130:
首先找到ting122,ting121发现事务id为120不可见,继续往下找到ting112,ting111 事务id为110同样不可见,在往下找到ting130事务id为130是可见的,所以返回ting130
再做个练习:
此时第14行的查询语句会返回什么?