mvcc
首先我们来做一个实验,用实验结果来分析问题
1.同时开启了五个事务开始执行,称为1,2,3,4,5事务吧
2.修改第三个事务,将employees id=1的数据修改为333并提交
3.第四个事务去查询刚才提交的第三个事务的结果,这个比较简单无异议
4.我们再回到第一个事务,操作一下employees表id = 1的数据(刚才第三个事务提交过的请求)
5 此时我们再用第四个事务查询下结果:
没有提交,所以还是333
6.提交第一个事务,再用第四个查询(结果还是333,是不是有点不一样了)
7.修改第二个事务 id=1的名称为222并提交
8. 第四个事务再次查询id = 1(结果还是333)
9.用第五个事务也查询同样的内容看看:
一样的语句,结果却不一样
这样看可能有点乱,贴个图看看流程吧
从上往下,按时间顺序执行,可以看到,第四个事务出来的结果和我们预想的都不太一样
为什么呢?
这就是mvcc的作用了:
mvcc 多版本并发控制机制 只在读已提交及可重复读下使用
保证事务执行的隔离性,就像上面不管事务1,2如何执行,事务4一直没有变动过
要了解如何操作的我们需要先明白两个东西:
undo日志版本链与read view机制(mvcc实现的机制就是靠这两)
undo日志:
同一行数据被多个事务修改后,每一个事务修改完成后,mysql会保留修改前的数据,用类似链表的形式。并且隐藏两个字段: trx_id(事务编号) 和 roll_pointer(滚动指针) 根据上面的例子,我们画个图来理解undo日志
说明一下执行的操作,结合上面的例子:
我把记录版本链分为了三种颜色:
黄色(代表已经提交的事务。是所有事务可见的)
红色(代表已提交和未提交事务)
绿色(未提交事务)
首先在可重复读隔离级别,开启事务后执行的所有查询都会当成当前事务的一致性视图(read-view),该视图在事务结束之前都不会变化(读已提交隔离基本每次查询都会重新生成视图),这个视图由执行查询时所有未提交事务id和已创建得最大事务id组成,事务里得查询结果都需要从版本链的最新数据(222)开始逐条往下跟read-view 做对比,得到最终的快照结果
我们执行了事务3(假定事务id为300)将name修改为333并提交,然后事务4查询到了已提交内容333 此时执行事务1(假定事务id为100) 将name修改成了111,因为一致性视图,事务4查询得时候还是333,执行事务2将name修改成222 同理。此时用事务5查询到name为222,已提交得事务
版本链比对规则:
三部分
1. 比对到版本是已提交部分,可见
2. 比对到版本是未提交部分,不可见
3. 对比到已提交与未提交部分,分两种
a 事务id在视图数组中,表示没有提交的事务生出。不可见
b 事务id不在视图数组中,表示已经提交的事务生成,可见
总结:
Buffer Pool
数据库缓冲池缓存机制,缓存表数据与索引数据,把磁盘上的数据加载到缓冲池,避免每次访问都进行磁盘IO,起到加速访问的作用。