MySQL调优-深入理解MVCC机制

目录

MySQL调优-深入理解MVCC机制

MVCC多版本并发控制机制

undo日志版本链与read view机制详解

 根据图2和图3对应画出下图的undo日志版本链:

版本链比对规则:

注意:

举例1:分析一下下图select1的read_view以及各个select语句查询到的结果 

(1)第一步:分析select1对应read_view的生成

 (2)第二步:根据最新生成的版本链+read_view进行比对得出当前select查询SQL的数据结果

举例2:在举例1的基础上搞一个select2

 当select2的查询语句执行后,生成select2对应事务结束前的唯一read_view:

其余的比对规则和举例1同理即可

总结:


MySQL调优-深入理解MVCC机制

MVCC多版本并发控制机制

MySQL在可重复读隔离级别下如何保证事务较高的隔离性,之前记录过,同样的sql查询语句在同一个事务里多次执行查询结果相同,就算其它事务对数据有修改也不会影响当前事务SQL语句的查询结果。

这个隔离性就是依靠MVCC机制来保证的,对一行数据的读和写两个操作默认是不会加锁互斥来保证隔离性,避免了频繁加锁互斥,而在串行化隔离级别为了保证较高的隔离性是通过将所有操作加锁互斥来实现的。

但是对于MySQL底层的读已提交和可重复读隔离级别下都是实现了MVCC机制。

undo日志版本链与read view机制详解

undo日志版本链是指一行数据被多个事务依次修改过后,在每个事务修改完后,MySQL会保留修改前的数据undo回滚日志,并且使用两个隐藏字段trx_id和roll_pointer把这些undo日志串联起来形成一个历史记录版本链。

MySQL调优-深入理解MVCC机制_第1张图片

图2:

MySQL调优-深入理解MVCC机制_第2张图片

图3:

MySQL调优-深入理解MVCC机制_第3张图片

 根据图2和图3对应画出下图的undo日志版本链:

MySQL调优-深入理解MVCC机制_第4张图片

版本链比对规则:

1. 如果 row 的 trx_id 落在绿色部分( trx_id

2. 如果 row 的 trx_id 落在红色部分( trx_id>max_id ),表示这个版本是由将来启动的事务生成的,是不可见的(若 row 的 trx_id 就是当前自己的事务是可见的);

3. 如果 row 的 trx_id 落在黄色部分(min_id<=trx_id<=max_id),那么就包括两种情况:

    a. 若 row 的 trx_id 在视图数组中,表示这个版本是由还没提交的事务生成的,不可见(若 row 的 trx_id 就是当前自己的事务是可见的);

    b. 若 row 的 trx_id 不在视图数组中,表示这个版本是已经提交了的事务生成的,可见。

注意:

(1)undo日志版本链只有一份。

(2)但是在可重复读隔离级别,当事务开启,执行任何查询sql时会生成当前事务的一致性视图read-view,该视图在事务结束之前都不会变化(如果是读已提交隔离级别在每次执行查询sql时都会重新生成),这个read_view视图由执行查询时所有未提交事务id数组(数组里最小的id为min_id)和已创建的最大事务id(max_id)组成。

事务里的任何sql查询结果需要从对应undo日志版本链里的最新数据开始逐条跟read_view做对比从而得到最终的快照结果,比对的过程依照的即是上面那个版本链比对规则这个快照结果即使最终select查询语句查询出的数据值。

(3)总结(1)和(2)

MySQL调优-深入理解MVCC机制_第5张图片

(4)对于删除的情况可以认为是update更新的特殊情况,会将版本链上最新的数据复制一份,然后将trx_id修改成删除操作的trx_id,同时在该条记录的头信息(record header)里的(deleted_flag)标记位写上true,来表示当前记录已经被 删除,在查询时按照上面的规则查到对应的记录如果delete_flag标记位为true,意味着记录已被删除,则不返回数 据。

(5)begin/start transaction 命令并不是一个事务的起点,在执行到它们之后的第一个修改操作InnoDB表的语句, 事务才真正启动,才会向mysql申请事务id,mysql内部是严格按照事务的启动顺序来分配事务id的。

即:只有当执行一次修改操作后mysql才会分配给事务id,如果一直执行select查询SQL,mysql不会分配事务id,begin/start transaction也没用!

举例1:分析一下下图select1的read_view以及各个select语句查询到的结果 

MySQL调优-深入理解MVCC机制_第6张图片

(1)第一步:分析select1对应read_view的生成

select1对应的事务没有执行修改SQL语句所以不生成事务id,但是由于执行了select查询语句,所以该事务会生成对应唯一一个read_view数组。

read_view生成规则如下:

在可重复读隔离级别下,当事务开启时,执行任何查询sql时会生成当前事务的一致性视图read-view,该视图在事务结束之前都不会变化(如果是读已提交隔离级别在每次执行查询sql时都会重新生成)。这个视图由执行查询时所有未提交事务id数组(数组里最小的id为min_id)和已创建(已commit提交)的最大事务id(max_id)组成。

根据生成规则以及上图开启的事务可知以及当第一条select查询语句执行后,在可重复读隔离机制下当前事务的read_view就已经确定了!分析如下:

1.一共开启了三个事务,事务id分别为100,200,300。其中100,200为未提交的事务。300为已创建(即是已提交)的事务。因此得出min_id=100,max_id=300。

2.当前select1对应的read_view为:[100,200],300。

3.其中[100,200]之间即是视图数组范围,300为非视图数组范围。

画出read_view示意图:

MySQL调优-深入理解MVCC机制_第7张图片

 (2)第二步:根据最新生成的版本链+read_view进行比对得出当前select查询SQL的数据结果

1.

事务里的任何sql查询结果需要从对应版本链里的最新数据开始逐条跟read-view做比对从而得到最终的快照结果。

2.版本链比对规则:

MySQL调优-深入理解MVCC机制_第8张图片

3.read_view示意图:

MySQL调优-深入理解MVCC机制_第9张图片

4.根据1和2和3可知,分析如下:

4.1当执行完第一条select查询后:

生成read_view为[100,200],300。其中[100,200]为视图数组范围,300为非视图数组范围。

在第一条select执行之前,一共有两条关于accout表的name字段的修改操作,一个是事务id为80(题目中未显示,篇幅问题)和一个事务id为300。

画出此时undo日志版本链为:

MySQL调优-深入理解MVCC机制_第10张图片

 根据版本链比对规则,从对应版本链里的最新数据开始逐条跟read-view做比对:

最新的数据row如上图即可得知,最新的row对应的事务id为300,300在黄色区域并且300不在视图范围,所以可见。所以第一条select语句返回的数据结果为lilei300。

4.2当执行完第二条select查询后:

 在第二条select执行之前,一共有四条关于accout表的name字段的修改操作,一个是事务id为80(题目中未显示,篇幅问题)和一个事务id为300和两条事务id为100。

画出此时undo日志版本链为:

MySQL调优-深入理解MVCC机制_第11张图片

 根据版本链比对规则,从对应版本链里的最新数据开始逐条跟read-view做比对

1.最新的数据row如上图即可得知,最新的row对应的事务id为100,100落到黄色区域并且100在视图范围,所以不可见。

2.因为1中的row不可见,所以版本链下推比对下一条row,事务id为100,同理1即可

3.因为2中的row不可见,所以版本链继续下推比对下一条row,事务id为300,300在黄色区域并且300不在视图范围,所以可见。

所以第二条select语句返回的数据结果为lilei300。

4.3当执行完第三条select查询后:

  在第三条select执行之前,一共有六条关于accout表的name字段的修改操作,一个是事务id为80(题目中未显示,篇幅问题)和一个事务id为300和两条事务id为100和两条事务id为200。

画出此时undo日志版本链为:

MySQL调优-深入理解MVCC机制_第12张图片

根据版本链比对规则,从对应版本链里的最新数据开始逐条跟read-view做比对

这个比对和4.2同理,省略了。

所以第三条select语句返回的数据结果为lilei300。

举例2:在举例1的基础上搞一个select2

由于举例1以及详细分析过了,所以这里简略记录一下。

MySQL调优-深入理解MVCC机制_第13张图片

MySQL调优-深入理解MVCC机制_第14张图片

 当select2的查询语句执行后,生成select2对应事务结束前的唯一read_view:

由执行查询时所有未提交事务id数组(数组里最小的id为min_id)和已创建的最大事务id(max_id)组成

1.一共开启了三个事务。事务id分别为100,200,300。

其中200为未提交的事务。100,300为已创建(即是已提交)的事务。未提交事务id数组中只有200,已创建的最大事务id为300。因此得出min_id=200,max_id=300。

2.当前select1对应的read_view为:[200],300。

3.其中[200]即是视图数组范围,300为非视图数组范围。

其余的比对规则和举例1同理即可

最终select2中查询语句查询出的数据结果为:lilei2

总结:

MVCC机制的实现就是通过read-view机制与undo版本链比对机制,使得不同的事务会根据数据版本链对比规则读取同一条数据在版本链上的不同版本数据。

你可能感兴趣的:(MySQL高级调优,缓存,mysql,java)