用十一张图讲清楚,当你CRUD时BufferPool中发生了什么!以及BufferPool的优化!
一、收到了大佬们的建议
1、篇幅偏短,建议稍微加长一点。
这点说的确实挺对,有的篇幅确实比较短,针对这个提议我会考虑将相似的话题放在一篇文章中。但是这可能会导致我中断每天更新的步调,换成隔几天发一篇的步调(但是这个系列的文章一定会写完的!)
2、Buffer Pool、LRU List、Flush List、Free List相辅相成,建议放在一起串讲。
说的没错,是应该一起串讲。于是有了这篇加餐的文章:下面让我们就一起看下,当你执行CURD时,InnoDB的Buffer Pool中都发生了什么!以及Buffer Pool的优化!
二、Let‘s go
你知道的,MySQL对数据的增删改查都是内存中完成的,这块内存就是Buffer Pool。
你可以像下面这样查看下你的MySQL的Buffer的Buffer Pool的默认大小
上图中的0.125单位为GB,转换成MB就是 1024* 1/8 = 128MB
总结来说,就是MySQL启动后就会为我们初始化好这块Buffer Pool。如下图:
你可以看着上图,然后读下面这段话:
MySQL以数据页为单位,从磁盘中读取数据。数据页被读取到内存中,所谓的内存其实就是Buffer Pool。
Buffer Pool中维护的数据结构是缓存页,而且每个缓存页都有它对应的描述信息。
由于MySQL刚启动,还没有从磁盘中读取任何数据页到内存(Buffer Pool)中,那此时Buffer Pool中所有的缓存页其实都是空的。
除了缓存页之外,你还能看到Buffer Pool中存在三个双向链表。分别是FreeList、LRUList以及FlushList。这三个双向链表中维护着缓存页的描述信息。
三、好,假设你读取出来了1个数据页
当你通过select读取出一个数据页之后,是需要将这个数据页加载进Buffer Pool中的缓存页中的。
那问题来了,MySQL怎么知道该将你读取出来的数据页存放在那个缓存页中呢?相信你看了上图应该也能想到答案了。FreeList这个双向链表不是存放了空闲的缓存页的描述信息吗?那从FreeList中取出一个空间缓存页的描述信息不就好了?于是得到了下面这张图:
啰嗦一点:对这张图稍微做一下解读:
InnoDB会将你读取出来的数据页加载进Buffer Pool中的缓存页中,然后缓存页的描述信息也会被维护进LRU链表中。链表做了冷热数据分离优化,5/8的区域是热数据区域,3/8的区域算是冷数据区域。(本质上它们都是双向链表),而你新读取的数据页会被放在冷数据区的靠前的位置上。
如果你将该数据页读取出来加载进缓存页中后,间隔没到1s,就使用该缓存页。那么InnoDB是不会将这个描述信息移动到5/8的热数据区域的。
但是当超过1s后,你又去读这个数据页。那这个数据页的描述信息就会被放到热数据区域。如下图:
四、假设你一次性读取出来了好多数据页
白日梦在第 6 篇文章中跟大家分享过,MySQL是存在预读机制的,感兴趣可关注公众号阅读。
假设触发了MySQL的预读机制。一次性从磁盘中读取来N多个缓存页。会得到下面这张图:
因为发生了预读,所以你的一次磁盘IO读出了大量的数据页,但是这些数据页中很可能是有一些是你根本不需要的,仅仅是预读把它们级联查出来了。这时按老规矩,从FreeList中找到空闲的缓存页信息,然后将其从FreeList中移除。根据找到的空闲缓存页的描述信息,将从磁盘中读取出来的数据页加载进去。相应的该缓存页的描述信息也会被维护进LRU链表的冷数据区域。
这时你就会发现这种冷热数据分离的机制多么妙!即使发生了预读又怎么样?根本没有机会将热数据区的描述信息1挤下去。当内存不够用了需要将部分缓存页刷新到磁盘中时,那就从冷数据区域开始刷新好了,反正他们本来就不经常被使用。
同样的,当你超过1s后又访问了冷数据区的缓存页,比如访问了缓存页66和数据页67,该缓存页对应的描述信息是会被提升到热数据区,于是有了下面这张图:
那,如果你访问上图中的数据页67,它会移动到描述信息66所在节点的前面去吗?
其实MySQL的LRU链表做了优化,数据67是不会往前跑的。
五、假设你修改了某数据页
假设你执行了update xxx set xxx where id in (xxx,xxx,xxx,xxx);
而符合条件的数据行恰巧就在描述信息1、描述信息66、描述信息67所指向的缓存页中,那BufferPool中会发生什么呢?
如下图:
你会看到,被你修改了的缓存页的描述信息,被添加到了FlushList这个双向链表中。
想必看到这里你已经知道了,原来FlushList中的节点存放就是被修改了脏数据页的描述信息块。
随着MySQL被使用的时间越来越长,BufferPool的大小就越来越小。等它不够用的时候,就会将部分LRU中的数据页描述信息移除出去,这时如果发现被移除出来的数据页在FLushList中,就会触发fsync的操作,触发随机写磁盘。如果该数据页是干净的,那移除出去就好了。其他也不用干啥。
举个例子:假设需要将描述信息66、描述信息67指向的缓存页落盘。会得到下面这张脑图:
描述信息66、67指向的缓存页被刷新进磁盘。 同时从FlushList中将其移除,然后存入FreeList中。完成一个循环
当然,将脏数据页刷新进磁盘的时机除了上图中说的还有好多种情况,白日梦在上一篇文章中有分享。可关注公众号查看哦
下面再看一下关于Buffer Pool的设置和相关的优化。
六、配置Buffer Pool的大小
buffer pool越大,MySQL的性能就越强悍。你可以像下面这样配置Buffer Pool的大小。
mysql> SET GLOBAL innodb_buffer_pool_size=402653184;
七、配置多个Buffer Pool的实例
你可以为MySQL实例配置多个Buffer Pool,每个Buffer Pool各自负责管理一部分缓存页,并且有自己独立的LRU、Free、Flush链表。
当有多线程并发请求过来时,线程可以在不同的Buffer Pool中执行自己的操作,MySQL性能就会得到很大的提升
在my.d中进行配置
[server]
innodb_buffer_pool_size = xxx
innodb_buffer_pool_instances = 4
意思是将总容量为xxx的buffer pool划分成4个实例。每个实例都有 xxx/4 的容量。
参数innodb_buffer_pool_instances
的最大值为64,并且想让该参数生效,innodb_buffer_pool_size
容量至少是1G。
可以像下面这样查看你的MySQL的Buffer Pool实例状态。
八、揭秘BufferPool的真实结构
现实中Buffer Pool动辄就占用好几G的内存,相对于直接申请几G的内存完成扩容,MySQL有更优雅的实现方式。
为了实现动态调整Buffer Pool的大小。MySQL设计了chunk 机制。
可以看上图脑补一下Buffer Pool 以及 Chunk长什么样。
总的来说:就是将每一个 Buffer Pool Instance 更加细力度化。将Buffer Pool拆分成更小的独立单元。
每个Buffer Pool划分成多个chunnk,每个chunk中维护一部分缓存页、缓存页的描述信息。同属于一个Buffer Pool的chunk共享该Buffer Pool的lru、free、flush链表。
块大小由参数innodb_buffer_pool_chunk_size
控制,默认值为 128M
该参数可以像下面这样修改:
shell> mysqld --innodb-buffer-pool-chunk-size=134217728
或者通过配置文件自定义
[mysqld]
innodb_buffer_pool_chunk_size=134217728
九、看一看Buffer Pool相关的参数
执行命令
> mysql show engine innodb status
十、如何规划你的Buffer Pool大小
推荐将Buffer Pool的总大小设置为服务器内存的 50%~60%左右
BufferPool总大小 = (chunkSize * bufferPoolInstanceNum)*2
十一、Buffer Pool的预热机制
这种机制实际上是想让重启后的MySQL快速适应大规模的流量请求。
InnoDB 在服务器关闭时为每个缓冲池保存一部分最近高频使用的页面,并在服务器启动时恢复这些页面。保存多大比例的缓存页由参数innodb_buffer_pool_dump_pct
控制。
在启动时还原缓冲池,实际上会缩短预热的时间。
你可以通过下面的方式配置该参数
# 通过命令
SET GLOBAL innodb_buffer_pool_dump_pct=40;
# 通过文件
[mysqld]
innodb_buffer_pool_dump_pct=40
参数innodb_buffer_pool_dump_at_shutdown
控制 MySQL关闭时保存缓冲池的状态,默认为on的状态。
启动参数--innodb-buffer-pool-load-at-startup
表示启动MySQL的时候恢复缓冲池中的状态,默认也是开启的。
关注送书!《Netty实战》
文章公号 首发!连载中!关注微信公号回复:“抽奖” 还可参加抽活动
诚信第一,活动真实有效
参考:
https://dev.mysql.com/doc/refman/5.7/en/innodb-buffer-pool-resize.html
https://dev.mysql.com/doc/refman/5.7/en/innodb-preload-buffer-pool.html
https://dev.mysql.com/doc/refman/5.7/en/innodb-preload-buffer-pool.html
https://dev.mysql.com/doc/refman/5.7/en/innodb-buffer-pool-resize.html
https://dev.mysql.com/doc/refman/5.7/en/innodb-buffer-pool.html
https://dev.mysql.com/doc/refman/5.7/en/innodb-performance-midpoint_insertion.html
https://dev.mysql.com/doc/refman/5.7/en/innodb-performance-read_ahead.html
https://dev.mysql.com/doc/refman/8.0/en/innodb-buffer-pool.html
https://lalitvc.wordpress.com/2016/11/03/mysql-architecture-and-components/
用十一张图讲清楚,当你CRUD时BufferPool中发生了什么!以及BufferPool的优化!的更多相关文章
- 一张图讲清楚TCP流量控制
- 一张图搞懂Ubuntu安装时姓名、计算机名、用户名
安装Ubuntu时会要求填写如下图的信息: 感谢:苏守坤 注意:上面的博客讲述了各自的具体含义,本篇博客只是说明这些名称在系统安装后会出现的位置.
- HTML5利用canvas,把多张图合并成一张图片
需求分析,根据当前网页中的几张图片,在手机上长按,保存图片到相册或者发送给好友. drawCanvas(){ var self = this; var imgsrcArray = [ require( ...
- 想了解Java后端学习路线?你只需要这一张图!
前言 学习路线图往往是学习一样技术的入门指南.网上搜到的Java学习路线图也是一抓一大把. 今天我只选一张图,仅此一图,足以包罗Java后端技术的知识点.所谓不求最好,但求最全,学习Java后端的同学 ...
- 干货 | 45张图庖丁解牛18种Queue,你知道几种?
在讲<21张图讲解集合的线程不安全>那一篇,我留了一个彩蛋,就是Queue(队列)还没有讲,这次我们重点来看看Java中的Queue家族,总共涉及到18种Queue.这篇恐怕是市面上最全最 ...
- 一张图告诉你,只会HTML还不够!
会了HTML和HTML5语法,你就真的会了HTML吗,来看这张图!是这本<超实用的HTML代码段>入门实例书的导览!熊孩子们,赶紧学习去吧! 如果一半以上的你都不会,必须看这本书,阿里一线 ...
- 一张图系列——为什么在DllMain里面创建了线程并Wait会卡死
这是一个老话题了,推荐一篇文章: http://blog.csdn.net/breaksoftware/article/details/8150476#0-tsina-1-83826-39723281 ...
- 一张图解释SQL Server集群、镜像、复制、日志传送
一张图解释SQL Server集群.镜像.复制.日志传送 本文版权归作者所有,未经作者同意不得转载.
- 深入理解javascript作用域系列第五篇——一张图理解执行环境和作用域
× 目录 [1]图示 [2]概念 [3]说明[4]总结 前面的话 对于执行环境(execution context)和作用域(scope)并不容易区分,甚至很多人认为它们就是一回事,只是高程和犀牛书关 ...
随机推荐
- Vue +WebSocket + WaveSurferJS 实现H5聊天对话交互
引言 在与实现了语音合成.语义分析.机器翻译等算法的后端交互时,页面可以设计成更为人性化.亲切的方式.我们采用类似于聊天对话的实现,效果如下: 智能客服(输入文本,返回引擎处理后的文本结果) 语音合成 ...
- C++类模板声明与定义为何不能分开
我们用C++写类的时候,通常会将.cpp和.h文件分开写,即实现和声明分开写了:但在C++的类模板中,这种写法是错误的. 在<C++编程思想>的第16章的"16.3模板语法&qu ...
- 洛谷 P2503 [HAOI2006]均分数据 随机化贪心
洛谷P2503 [HAOI2006]均分数据(随机化贪心) 现在来看这个题就是水题,但模拟赛时想了1个小时贪心,推了一堆结论,最后发现贪心做 不了, 又想了半个小时dp 发现dp好像也做不了,在随机化 ...
- 微服务nacos服务注册与发现
一,以上一篇为基础 微服务从nacos配置中心获得配置信息 给service1, service2添加依赖 <dependency> <groupId>com.alibaba. ...
- B树摘要
BTree 以下内容是根据<算法导论>摘要而来,由于国内书籍对B树的定义是以阶来定义,而<算法导论>中使用的是最小度来定义,并且节点中关键字个数也不相同,在翻看网上博客时,产生 ...
- vue-cli3生产环境和开发环境路径的替换
在根目录下创建两个文件,这样的好处在于不用手动去书写判断环境替换路径代码 .env.development(开发) .env.production(生产) 内容: 必须是VUE_APP前缀开头,这样w ...
- Win32之创建进程
CreateProcess函数介绍 BOOL CreateProcessA( LPCSTR lpApplicationName, //可执行文件的名称完整的路径+程序名字) LPSTR lpComma ...
- C#设计模式-模板方法模式(Template Method)
概念 模板指一些可以套用的公共内容,例如网页模板是当网站中有许多页面版式色彩相同的情况下,将其定义为网页模板,并定义其中部分可编辑,部分不可编辑,那么在利用网页模板制作其他页面时就会很方便,不易出错. ...
- [Luogu P3469] [POI2008]BLO-Blockade (割点)
题面 传送门:https://www.luogu.org/problemnew/show/P3469 Solution 先跟我大声念: poi! 然后开始干正事. 首先,我们先把题目中的点分为两类:去 ...
- python pip源国内加速
Pip源国内加速list 清华:https://pypi.tuna.tsinghua.edu.cn/simple 阿里云:http://mirrors.aliyun.com/pypi/simple/ ...