MySQL:当你CRUD时BufferPool中发生了什么?十张图就能说清楚

一、前言

你知道的,MySQL对数据的增删改查都是内存中完成的,这块内存就是Buffer Pool。

你可以像下面这样查看下你的MySQL的Buffer的Buffer Pool的默认大小

image

上图中的0.125单位为GB,转换成MB就是 1024* 1/8 = 128MB

总结来说,就是MySQL启动后就会为我们初始化好这块Buffer Pool。如下图:

image

你可以看着上图,然后读下面这段话:

MySQL以数据页为单位,从磁盘中读取数据。数据页被读取到内存中,所谓的内存其实就是Buffer Pool。

Buffer Pool中维护的数据结构是缓存页,而且每个缓存页都有它对应的描述信息。

由于MySQL刚启动,还没有从磁盘中读取任何数据页到内存(Buffer Pool)中,那此时Buffer Pool中所有的缓存页其实都是空的。

除了缓存页之外,你还能看到Buffer Pool中存在三个双向链表。分别是FreeList、LRUList以及FlushList。这三个双向链表中维护着缓存页的描述信息。

二、好,假设你读取出来了1个数据页

当你通过select读取出一个数据页之后,是需要将这个数据页加载进Buffer Pool中的缓存页中的。

那问题来了,MySQL怎么知道该将你读取出来的数据页存放在那个缓存页中呢?相信你看了上图应该也能想到答案了。FreeList这个双向链表不是存放了空闲的缓存页的描述信息吗?那从FreeList中取出一个空间缓存页的描述信息不就好了?于是得到了下面这张图:

image

啰嗦一点:对这张图稍微做一下解读:

InnoDB会将你读取出来的数据页加载进Buffer Pool中的缓存页中,然后缓存页的描述信息也会被维护进LRU链表中。链表做了冷热数据分离优化,5/8的区域是热数据区域,3/8的区域算是冷数据区域。(本质上它们都是双向链表),而你新读取的数据页会被放在冷数据区的靠前的位置上。

如果你将该数据页读取出来加载进缓存页中后,间隔没到1s,就使用该缓存页。那么InnoDB是不会将这个描述信息移动到5/8的热数据区域的。

但是当超过1s后,你又去读这个数据页。那这个数据页的描述信息就会被放到热数据区域。如下图:

image

三、假设你一次性读取出来了好多数据页

白日梦在第 6 篇文章中跟大家分享过,MySQL是存在预读机制的,感兴趣可关注公众号阅读。

假设触发了MySQL的预读机制。一次性从磁盘中读取来N多个缓存页。会得到下面这张图:

image

因为发生了预读,所以你的一次磁盘IO读出了大量的数据页,但是这些数据页中很可能是有一些是你根本不需要的,仅仅是预读把它们级联查出来了。这时按老规矩,从FreeList中找到空闲的缓存页信息,然后将其从FreeList中移除。根据找到的空闲缓存页的描述信息,将从磁盘中读取出来的数据页加载进去。相应的该缓存页的描述信息也会被维护进LRU链表的冷数据区域。

这时你就会发现这种冷热数据分离的机制多么妙!即使发生了预读又怎么样?根本没有机会将热数据区的描述信息1挤下去。当内存不够用了需要将部分缓存页刷新到磁盘中时,那就从冷数据区域开始刷新好了,反正他们本来就不经常被使用。

同样的,当你超过1s后又访问了冷数据区的缓存页,比如访问了缓存页66和数据页67,该缓存页对应的描述信息是会被提升到热数据区,于是有了下面这张图:

image

那,如果你访问上图中的数据页67,它会移动到描述信息66所在节点的前面去吗?

其实MySQL的LRU链表做了优化,数据67是不会往前跑的。

四、假设你修改了某数据页

假设你执行了update xxx set xxx where id in (xxx,xxx,xxx,xxx);

而符合条件的数据行恰巧就在描述信息1、描述信息66、描述信息67所指向的缓存页中,那BufferPool中会发生什么呢?

如下图:

image

你会看到,被你修改了的缓存页的描述信息,被添加到了FlushList这个双向链表中。

想必看到这里你已经知道了,原来FlushList中的节点存放就是被修改了脏数据页的描述信息块。

随着MySQL被使用的时间越来越长,BufferPool的大小就越来越小。等它不够用的时候,就会将部分LRU中的数据页描述信息移除出去,这时如果发现被移除出来的数据页在FLushList中,就会触发fsync的操作,触发随机写磁盘。如果该数据页是干净的,那移除出去就好了。其他也不用干啥。

举个例子:假设需要将描述信息66、描述信息67指向的缓存页落盘。会得到下面这张脑图:

描述信息66、67指向的缓存页被刷新进磁盘。 同时从FlushList中将其移除,然后存入FreeList中。完成一个循环

image

当然,将脏数据页刷新进磁盘的时机除了上图中说的还有好多种情况。

下面再看一下关于Buffer Pool的设置和相关的优化。

五、配置Buffer Pool的大小

buffer pool越大,MySQL的性能就越强悍。你可以像下面这样配置Buffer Pool的大小。

Copymysql> SET GLOBAL innodb_buffer_pool_size=402653184;

六、配置多个Buffer Pool的实例

你可以为MySQL实例配置多个Buffer Pool,每个Buffer Pool各自负责管理一部分缓存页,并且有自己独立的LRU、Free、Flush链表。

当有多线程并发请求过来时,线程可以在不同的Buffer Pool中执行自己的操作,MySQL性能就会得到很大的提升

在my.d中进行配置

Copy[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实例状态。

image

七、揭秘BufferPool的真实结构

现实中Buffer Pool动辄就占用好几G的内存,相对于直接申请几G的内存完成扩容,MySQL有更优雅的实现方式。

为了实现动态调整Buffer Pool的大小。MySQL设计了chunk 机制。

image

可以看上图脑补一下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

该参数可以像下面这样修改:

Copyshell> mysqld --innodb-buffer-pool-chunk-size=134217728

或者通过配置文件自定义

Copy[mysqld]
innodb_buffer_pool_chunk_size=13421772

八、看一看Buffer Pool相关的参数#

执行命令

Copy> mysql show engine innodb status
image

九、如何规划你的Buffer Pool大小

推荐将Buffer Pool的总大小设置为服务器内存的 50%~60%左右

BufferPool总大小 = (chunkSize * bufferPoolInstanceNum)*2

十、Buffer Pool的预热机制

这种机制实际上是想让重启后的MySQL快速适应大规模的流量请求。

InnoDB 在服务器关闭时为每个缓冲池保存一部分最近高频使用的页面,并在服务器启动时恢复这些页面。保存多大比例的缓存页由参数innodb_buffer_pool_dump_pct控制。

在启动时还原缓冲池,实际上会缩短预热的时间。

你可以通过下面的方式配置该参数

Copy# 通过命令
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的时候恢复缓冲池中的状态,默认也是开启的。

原文链接:https://www.cnblogs.com/ZhuChangwu/p/14018273.html

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容

  • Schema与数据类型优化 选择优化的数据类型 有几个简单的原则: 更小的通常更好一般情况下使用可以正确存储数据的...
    陈晨_软件五千言阅读 3,459评论 1 65
  • 1. 系统是如何跟MySQL打交道的 系统采用数据库连接池的方式去并发访问数据库,然后数据库自己其实也会维护一个连...
    herohua阅读 893评论 0 0
  • 基于LRU算法淘汰部分缓存 今天我们接着来分析buffer pool的工作原理。我们来思考一个问题,当你要执行CR...
    为爱放弃一切阅读 354评论 0 2
  • 表情是什么,我认为表情就是表现出来的情绪。表情可以传达很多信息。高兴了当然就笑了,难过就哭了。两者是相互影响密不可...
    Persistenc_6aea阅读 120,608评论 2 7
  • 16宿命:用概率思维提高你的胜算 以前的我是风险厌恶者,不喜欢去冒险,但是人生放弃了冒险,也就放弃了无数的可能。 ...
    yichen大刀阅读 5,980评论 0 4