深入理解MySQL中MVCC与BufferPool缓存机制


Posted in MySQL onMay 25, 2022

一、MVCC机制

  • MVCC(Multi Version Concurrency Control),MySQL(默认)RR隔离级别就是通过该机制来保证的,对一行数据的读与写两个操作默认是不会通过加锁互斥来保证隔离性的
  • 串行化隔离级别是为了保证较高的隔离性,是通过将所有操作加锁互斥来实现的
  • MySQL在RC隔离级别和RR隔离级别下都实现了MVCC机制
  • RC每次查询都会创建一个reade-view,而RR在创建完read-view之后,在不提交事务之前,每次查询还是第一次创建的read-view

undo日志版本链与read-view机制

  • undo日志版本链是指一行数据被多个事务一次修改后,当每个事务修改完之后,MySQL会保留修改前的数据undo回滚日志,并且用两个隐藏字段trx_id和roll_pointer把只写undo日志串联起来形成一个历史记录版本链.
  • RR隔离级别,当事务开启,执行任何SQL时会生成当前事务的read-view一致性视图,该视图在事务结束之前都不会变化(如果是RC隔离界别在每次执行查询SQL时都会重新生成最新的read-view),这个视图由执行查询时所有未提交的事务id数组(数组里最小的id为min_id)和已创建的最大事务id(max_id)组成,事务里任何SQL查询结果需要从对应版本链里的最新数据开始逐条跟read-view作比对,从而得到最终的结果

版本链比对规则

  • 如果row的trx_id落在绿色部分(trx < min_id),表示这个版本是已提交的事务生成的,这个数据是可见的
  • 如果row的trx_id落在红色部分(trx > max_id),表示这个版本是由将来启动的(未开始)事务生成的,是不可见的(若row的trx_id就是当前自己的事务是可见的)
  • 如果 row 的 trx_id 落在黄色部分(min_id <= trx_id <= max_id),那就包括两种情况
    • 若 row 的 trx_id 在视图数组中,表示这个版本是由还没提交的事务生成的不可见(若 row 的 trx_id 就是当前自己的事务是可见的)
    • 若 row 的 trx_id 不在视图数组中,表示这个版本是已经提交了的事务生成的可见

深入理解MySQL中MVCC与BufferPool缓存机制

二、BufferPool机制

InnoDB执行的BufferPool缓存机制:

深入理解MySQL中MVCC与BufferPool缓存机制

InnoDB的SQL执行流程:

  • 当客户端执行一条修改的SQL,需要经过Server层,再调用具体的执行引擎
  • 加载数据页,把需要修改数据所在的数据页,缓存到BufferPool
  • 修改前写undo日志,记录更改前数据,如果事务执行失败,使用undo日志进行数据回滚
  • 更新BufferPool中的数据
  • 准备提交事务写redo日志,保存操作记录。redo日志用来恢复已提交事务的BufferPool
  • 准备提交事务写binlog日志,保存操作记录。binlog日志用来恢复磁盘数据
  • 事务提交完成,此时binlog日志写入成功,并且在redo日志中记录了commit标记。事务提交完成后binlog日志和redo日志数据保持一致
  • 数据持久化,IO线程不定期把BufferPool中的数据随机写入到磁盘,完成持久化

三、总结

MVCC实现机制(为什么同一个事务第一次查询出来之后,就算其它事务把新数据修改了,当前事务还是看到之前的数据)

  • 它内部实际有个undo日志版本链,然后在事务第一次查询的时候,它会生成一个read-view一致性视图,然后我们后面所有查询的数据都会根据我们的那个undo日志版本链去跟我们当前的read-view里面按照一定的规则逐行去比对查找对应的数据

BufferPool机制

  • 数据库的增删改查都是直接操作BufferPool的,当我们执行一条修改的SQL经历过Server层之后会调用具体的执行引擎,然后将相关的数据页加载到BufferPool中,修改前写undo日志,记录修改前的数据为了方便事务失败之后的回滚,然后更新BufferPool,准备提交事务写redo日志保存操作记录,因为如果MySQL宕机了会从redo日志中将数据恢复到BufferPool中,然后会写binlog日志,保存操作记录,因为当我们删除数据库跑路时,binlog是用来恢复磁盘数据的,事务提交完成后,binlog日志写入成功,并且在redo日志记录提交标记,此时redo日志和binlog日志数据一致,而redo日志采用顺序IO写入,这样效率堪比内存操作。对于数据持久化,InnoDB会有个后台线程定时去将缓存刷到磁盘里

为什么MySQL不能直接更新磁盘上的数据而是设置了这么一套复杂的机制来执行SQL

  • 因为来一个请求直接对磁盘文件进行随机读写,然后更新磁盘文件里的数据性能可能相当差.
  • 因为磁盘随机读写的性能是非常差的,所以直接更新磁盘文件时不能让数据库抗住高并发的
  • MySQL这套机制看起来很复杂,但它可以保证每个更新请求都是更新内存BufferPool,然后顺序写日志文件,同时还能保证各种异常情况下的数据一致性
  • 更新内存的性能是极高的,然后顺序写磁盘上的日志文件的性能也是非常高的,要远高于随机读写磁盘文件,正是通过这套机制,才能让我们的MySQL数据库在较高配置的机器上每秒可以抗下几千甚至上完的读写请求

到此这篇关于深入理解MySQL中MVCC与BufferPool缓存机制的文章就介绍到这了!


Tags in this post...

MySQL 相关文章推荐
MySQL复制问题的三个参数分析
Apr 07 MySQL
MySQL 聚合函数排序
Jul 16 MySQL
SQL实现LeetCode(175.联合两表)
Aug 04 MySQL
关于MySQL中的 like操作符详情
Nov 17 MySQL
Mysql数据库表中为什么有索引却没有提高查询速度
Feb 24 MySQL
一文搞懂MySQL索引页结构
Feb 28 MySQL
mysql使用instr达到in(字符串)的效果
Apr 03 MySQL
CentOS MySql8 远程连接实战
Apr 19 MySQL
MySQL 自动填充 create_time 和 update_time
May 20 MySQL
浅谈MySql update会锁定哪些范围的数据
Jun 25 MySQL
MySQL生成千万测试数据以及遇到的问题
Aug 05 MySQL
MySql统计函数COUNT的具体使用详解
Aug 14 MySQL
MYSQL事务的隔离级别与MVCC
详解Mysql数据库平滑扩容解决高并发和大数据量问题
MySQL中EXPLAIN语句及用法
May 20 #MySQL
Mysql 一主多从的部署
May 20 #MySQL
mysql 排序失效
May 20 #MySQL
MySQL 自动填充 create_time 和 update_time
May 20 #MySQL
MySQL数据库 任意ip连接方法
May 20 #MySQL
You might like
PHP编程网上资源导航
2006/10/09 PHP
解析如何用php screw加密php源代码
2013/06/20 PHP
Yii使用find findAll查找出指定字段的实现方法
2014/09/05 PHP
VPS中使用LNMP安装WordPress教程
2014/12/28 PHP
codeigniter发送邮件并打印调试信息的方法
2015/03/21 PHP
PHP伪造来源HTTP_REFERER的方法实例详解
2015/07/06 PHP
PHP实现一个简单url路由功能实例
2016/11/05 PHP
解决form中action属性后面?传递参数 获取不到的问题
2017/07/21 PHP
IE与Firefox下javascript getyear年份的兼容性写法
2007/12/20 Javascript
JQuery困惑—包装集 DOM节点
2009/10/16 Javascript
jQuery ctrl+Enter shift+Enter实现代码
2010/02/07 Javascript
Function.prototype.call.apply结合用法分析示例
2013/07/03 Javascript
js为数字添加逗号并格式化数字的代码
2013/08/23 Javascript
快速解决jquery之get缓存问题的最简单方法介绍
2013/12/19 Javascript
javascript电商网站抢购倒计时效果实现
2015/11/19 Javascript
基于JavaScript实现移除(删除)数组中指定元素
2016/01/04 Javascript
详解JS中的柯里化(currying)
2017/08/17 Javascript
Vue.JS实现垂直方向展开、收缩不定高度模块的JS组件
2018/06/19 Javascript
vue.js添加一些触摸事件以及安装fastclick的实例
2018/08/28 Javascript
vue-cli2.0转3.0之项目搭建的详细步骤
2018/12/11 Javascript
vue实现图片上传预览功能
2019/12/23 Javascript
基于JavaScript或jQuery实现网站夜间/高亮模式
2020/05/30 jQuery
vue实现用户长时间不操作自动退出登录功能的实现代码
2020/07/23 Javascript
听歌识曲--用python实现一个音乐检索器的功能
2016/11/15 Python
python将一组数分成每3个一组的实例
2018/11/14 Python
用python脚本24小时刷浏览器的访问量方法
2018/12/07 Python
Python3.5 Json与pickle实现数据序列化与反序列化操作示例
2019/04/29 Python
Python 取numpy数组的某几行某几列方法
2019/10/24 Python
Python格式化输出--%s,%d,%f的代码解析
2020/04/29 Python
HTML5的标签的代码的简单介绍 HTML5标签的简介
2012/05/28 HTML / CSS
销售人员自我评价怎么写
2013/09/19 职场文书
求职自荐信
2013/12/14 职场文书
教学评估实施方案
2014/03/16 职场文书
高校教师个人工作总结2014
2014/12/17 职场文书
反邪教观后感
2015/06/11 职场文书
上帝为你开了一扇窗之Tkinter常用函数详解
2021/06/02 Python