Mysql的MVCC机制与BufferPool缓存机制

写在前面

前面上一篇Mysql事务隔离级别和锁机制,可以看到MySQL在可重复读隔离级别下,可以保证事务较高的隔离性。这个隔离性是通过MVCC(Multi-Version Concurrency Control)机制来保证的,对一行数据的读和写两个操作默认是不会通过加锁互斥来保证隔离性,避免了频繁加锁互斥。

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

undo日志版本链是指一行数据被多个事务依次修改后,在每个事务修改后,Mysql会保留修改前的数据undo回滚日志,并且用两个隐藏字段trx_id和roll_pointer,把这些undo日志串联起来形成一个历史记录版本链。
如图所示:
image.png
可重复读隔离级别,当事务开启,执行任何查询sql时会生成当前事务的一致性视图read-view,该视图在第一次select的时候生成,在事务结束之前都不会变化如果是读已提交隔离级别在每次执行查询(select)sql时都会重新生成,read-veiw是由执行查询时所有未提交事务id数组里最小的id未min_id已创建的最大事务id(max_id)组成,事务里的任何sql查询结果都需要从对应版本链(上图)的最新数据开始逐一跟read-view做对比,从而得到最终的快照结果。
版本链比对规则
1.如果row的trx_id落在绿色区域(trx_id<min_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在视图数组(read-veiw)中,表示这个版本是由还没提交的事务生成的,不可见。
b.若row的trx_id不在视图数组中,表示这个版本是已经提交了的事务生成的,可见。
举例:
image.png
分析:
如图所示在不同时刻(1-13)进行事务80(trx_id 80)、事务100(trx_id 100)、事务200(trx_id 200)、事务300(trx_id 300)、查询1、查询2操作。trx_id 80可以认为是已经提交的事务。
时刻1:开启事务begin;
时刻2:trx_id 80提交事务,trx_id 100进行了一次update操作,事务未提交;
时刻3:trx_id 200进行了一次update操作,事务未提交;
时刻4、5:trx_id 300进行了一次update操作,并且提交了事务;
时刻6:select 1 进行了一次查询操作,此时会生成read-view,根据生成原则由最小未提交事务id(trx_id 100)和最大已创建事务id(trx_id 300)组成,即read-view:([100,200],300),根据版本链比对规则:此时的记录版本链条如下图:
image.png
此时的trx_id 为300,到read-view([100,200],300)中去比较发现不在[100,200]中,说明对查询select 1 可见。查询的结果为name300。
时刻7、8:trx_id 100进行了两次的update操作,但事务还未提交。此时的版本链条如下图:
image.png
时刻9:select 1进行了一次查询操作,在可重复读隔离级别下,因为在时刻6的时候,已经进行了一次查询操作,这时候的read-view还是([100,200],300),根据版本链比对规则:在最新的记录版本链条,从上往下找,先是trx_id 100,name是name2的记录,到read-view对比,发现在[100,200]中,对当前事务select 1不可见,继续往下找trx_id 100,name是name1的记录,同理得,对当前事务不可见,接着向下查找到,trx_id 300,name是300的记录,对比发现300不在[100,200]中,即对当前事务可见,于是查询结果为name300。
时刻10、11:trx_id 100提交了事务,trx_id 200进行了二次update操作,但事务还未提交。此时的版本链记录如下:
image.png
时刻12:select 1 进行了一次查询操作,同理可知select 1在之前已经进行过查询操作,因此,此时的read-view还是([100,200],300),分析步骤如时刻9所示,不做赘述。select 2进行了一次查询操作,因为select 2 是第一次查询,因此根据规则会生成read-view([200],300),根据版本链比对规则:从上往下查找trx_id 200,name为name4在[200]中,对当前事务不可见,同理的name为name3也对当前事务不可见,当到trx_id 100,name为name1时,发现trx_id 100 < trx_id 200,说明这个版本是已经提交的事务生成的,对当前事务可见。即查询结果为name2。
时刻13:trx_id 200 进行了commit操作。此时版本链条为本篇第一张图所示。

小结

对于删除的情况可以认为是update的特殊情况,会将版本链上最新的数据复制一份,然后将trx_id修改成删除操作的 trx_id,同时在该条记录的头信息(record header)里的(deleted_flag)标记位写上true,来表示当前记录已经被 删除,在查询时按照上面的规则查到对应的记录如果delete_flag标记位为true,意味着记录已被删除,则不返回数据。
注意:begin/start transaction 命令并不是一个事务的起点,在执行到它们之后的第一个修改操作InnoDB表的语句, 事务才真正启动,才会向mysql申请事务id,mysql内部是严格按照事务的启动顺序来分配事务id的。
MVCC机制的实现就是通过read-view机制与undo版本链比对机制,使得不同的事务会根据数据版本链对比规则读取 同一条数据在版本链上的不同版本数据。

Innodb引擎BufferPool缓存机制

免责声明:务必仔细阅读

  • 本站为个人博客,博客所转载的一切破解、path、补丁、注册机和注册信息及软件等资源文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。

  • 本站为非盈利性站点,打赏作为用户喜欢本站捐赠打赏功能,本站不贩卖软件等资源,所有内容不作为商业行为。

  • 本博客的文章中涉及的任何解锁和解密分析脚本,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断.

  • 本博客的任何内容,未经许可禁止任何公众号、自媒体进行任何形式的转载、发布。

  • 博客对任何脚本资源教程问题概不负责,包括但不限于由任何脚本资源教程错误导致的任何损失或损害.

  • 间接使用相关资源或者参照文章的任何用户,包括但不限于建立VPS或在某些行为违反国家/地区法律或相关法规的情况下进行传播, 博客对于由此引起的任何隐私泄漏或其他后果概不负责.

  • 请勿将博客的任何内容用于商业或非法目的,否则后果自负.

  • 如果任何单位或个人认为该博客的任何内容可能涉嫌侵犯其权利,则应及时通知并提供身份证明,所有权证明至admin@proyy.com.我们将在收到认证文件后删除相关内容.

  • 任何以任何方式查看此博客的任何内容的人或直接或间接使用该博客的任何内容的使用者都应仔细阅读此声明。博客保留随时更改或补充此免责声明的权利。一旦使用并复制了博客的任何内容,则视为您已接受此免责声明.

您必须在下载后的24小时内从计算机或手机中完全删除以上内容.

您使用或者复制了本博客的任何内容,则视为已接受此声明,请仔细阅读


更多福利请关注一一网络微信公众号或者小程序

一一网络微信公众号
打个小广告,宝塔服务器面板,我用的也是,很方便,重点是免费的也能用,没钱太难了,穷鬼一个,一键全能部署及管理,送你3188元礼包,点我领取https://www.bt.cn/?invite_code=MV9kY3ZwbXo=


一一网络 » Mysql的MVCC机制与BufferPool缓存机制

发表评论

发表评论

一一网络-提供最优质的文章集合

立即查看 了解详情