Mysql MVCC与BufferPool缓存机制学习总结

MVCC多版本并发控制机制

Mysql在可串行化隔离级别中使用锁机制来解决幻读问题,在可重复读隔离级别中对一行数据的读和写两个操作通过MVCC机制来解决幻读问题,避免了频繁加锁。
Mysql在读已提交和可重复读隔离级别下都实现了MVCC机制,首先要了解undo日志版本链与read view机制。

undo日志版本链:

针对一行数据,被多个事务依次修改过后,在每个事务修改完后,Mysql会保留修改前的数据undo回滚日志,Innodb表中会有两个隐藏字段trx_id和roll_pointer,undolog把这两个字段串联起来形成一个历史记录版本链。

read view一致性试图:

在可重复读隔离级别,当事务开启,执行任何查询sql时会生成当前事务的一致性视图read-view,该视图在事务结束之前都不会变化。
这个视图由执行查询时所有未提交事务id数组,和已创建的最大事务id组成。数组里最小的id为min_id,最大事务id为max_id,查询不生成事务ID
事务里的任何sql查询结果需要从对应版本链里的最新数据开始逐条跟read-view做比对从而得到最终的快照结果。
在读已提交隔离级别中,每次执行查询sql时都会重新生成。
begin/start transaction 命令并不是一个事务的起点,在执行到它们之后的第一个修改操作InnoDB表的语句时,事务才真正启动,才会向mysql申请事务id,mysql内部是严格按照事务的启动顺序来分配事务id的,所以事物id是连续的

版本链比对规则:

底层会把read view 分为三部分存放,分别为已提交事务、未提交与已提交事务、未开始事务。

已提交事务区间:trx_id < min_id
未开始事务区间: trx_id > max_id 
未提交与已提交事务区间:trx_id >= min_id && <= max_id

会根据undo日志中的最新trx_id来对比:
1、如果trx_id在已提交事务(绿色)区间,表示这个版本是已提交的事务生成的,数据可见;
2、如果trx_id在未开始事务(红色)区间,表示这个版本是由将来启动的事务生成的,数据不可见;
3、如果trx_id 在未提交与已提交事务(黄色)区间,那就包括两种情况:
  a. 如果trx_id在数组中,表示这个版本是由还没提交的事务生成的,数据不可见。
  b. 如果trx_id不在数组中,表示这个版本是已经提交了的事务生成的,数据可见。
MVCC执行过程:

请添加图片描述
下图中,针对user表中id=1的这条数据,有三个事务依次开启:transaction100、transaction200、transaction300,数据库初始name为lucy。
1、事务300把name修改为lucy300,紧接着commit。undo中会新增一条事务id为300的日志记录,此时执行了第一次查询sql,生成的read view为:[100,200], 300。读取数据时,会从undo中拿到最新版本的事务id去跟read view做比较,此时最新的事务id为300,根据对比规则,事务300在黄色区间,并且不在数组中,数据是可见的,所以返回lucy300。

2、接着事务100把name修改了两次,分别为lucy1,lucy2,此时read view日志新增了两条事务100的操作记录,最新的为name=lucy2。之后又做了第二次查询,因为查询在同一个事务中,所以read view 不变,此时根据对比规则,事务100在黄色区间,并且在数组中,数据是不可见的,所以继续向上找日志记录,还是事务100,继续找,找到事务300,所以返回lucy300。

3、接着事务100提交了事务,事务200也把name修改了两次,分别为lucy3,lucy4,read view日志又新增了两条事务200的操作记录,最新的为name=lucy4,之后又做了第三次查询,此时根据对比规则,事务200在黄色区间,并且在数组中,数据不可见,所以向上查找,直到找到事务300,返回lucy300。

4、在第三次查询时,另一个事务又同时开启了一条查询语句,那么将会生成新的read view:[200],300,根据对比规则,最新日志是事务200的两条更新值,事务200在黄色区间,并且在数组中,所以向上继续查询,事务100在绿色区间,数据可见,所以返回lucy2,此时数据库中实时的值也是lucy2。
请添加图片描述

BufferPool缓存机制

请添加图片描述

Mysql这套机制可以保证每个更新请求都是更新内存BufferPool,更新内存的性能是极高的,然后顺序写日志文件,顺序写磁盘上的日志文件的性能也是非常高的,要远高于随机读写磁盘文件,同时还能保证各种异常情况下的数据一致性。

总结:

RR隔离级别下,Mysql通过MVCC+临键锁机制来解决幻读问题,临键锁解决当前读(update、insert、delete)的幻读问题,MVCC解决快照读的幻读问题。
MVCC是多半本并发控制,它会为事物分配一个时间戳,通过时间戳来确定事物的先后顺序,实现注册并发控制。MVCC通过两个隐式字段;undolog;read view三部分来实现的。两个隐式字段分别是当前事物id、回滚指针,它们和undolog一起维护了一个版本链,版本链的生成规则是在更改数据库数据的时候,会先用排他锁锁住这行数据,把这行记录复制到undolog里,同时把回滚指针指向这行记录,这样每条修改记录就会维护在这套版本链中。还有就是read-view视图,事物开启后,执行第一条查询时会生成一个read view视图快照,这个视图在事务结束之前都不会变化。视图由所有未提交事务id数组、已创建的最大事务id两部分组成,并且分为三个区间存放,分别为已提交事务、未提交与已提交事务、未开始事务,当前事物id < 未提交事物数组中的最小事物id的是就是已提交的事物,当前事物id > 未提交事物数组中的最大事物id的是未开始的事物,未提交事物数组中的事物是未提交与已提交的事务。其中,已提交事物是可见的,未开始事物是不可见的,如果事物id在数组中,数据是不可见的,如果事物id不在数组中,数据是可见的。查询时,会从undolog中拿到最新版本的事务id去跟read view做比较,根据对比规则判断该数据是否对其他事物可见,从而解决幻读问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值