mysql笔记十一:Buffer pool缓冲池

论坛 期权论坛 脚本     
匿名技术用户   2021-1-7 14:33   30   0

关键字: buffer pool、控制信息、free链表、flush链表、LRU链表、LRU分段、脏页、chunk

mysql从磁盘上加载数据页到内存中后,会在内存中做一个缓存,下次再需要加载数据页时,先去缓存中查找,如果能找到就直接使用,否则才去磁盘上加载数据页再放入缓存中。这个缓存就是buffer pool。

11.1、系统参数设置

(1)innodb_buffer_pool_size

缓存池是有大小限制的,参数为:innodb_buffer_pool_size,默认是128M。

(2)innodb_old_blocks_pct

LRU链表中,old区域占用的比例。

(3)innodb_buffer_pool_instances

buffer pool实例的个数

(4)innodb_buffer_pool_chunk_size

buffer pool中chunk的大小,默认128M

(5)innodb_old_blocks_time

当old区域中的页被再次访问时,如果再次访问的时间间隔小于innodb_old_blocks_time值的话,那么这个缓存页不会被加入young区域。

11.2、控制信息

对于缓存池buffer pool上的所有缓存页,innodb都用了一个控制信息块来记录这个缓存页的一些相关信息,包括表空间编号、页号、缓存页的地址、各种链表的信息、锁信息、LSN信息。

控制块不占用buffer pool的空间,一个控制块的大小为808字节,控制块和缓存页是一一对应的。

11.3、free链表

所有空闲的缓存页对应的控制块的链表称为free链表。

11.4、flush链表

当内存中的页中的数据被修改了后,并不会立即刷新到磁盘上,而是会在某个时间点去刷新进入磁盘,并且还要更新check_lsn的值。这些被修改了但未刷新回磁盘上的页被称为脏页(dirty page)。脏页形成一个链表,称为flush链表。结构和上图一样。

11.5、LRU链表

LRU:Least Recently Used:最近最少使用

当buffer pool中空闲页用完时,这时候还需要将磁盘中某些数据页加载到内存时,需要淘汰一些最近最少使用的缓存页,然后将新加载的页放入缓存池中。所以Innodb维护了一个LRU链表,处于链表末端的数据就是最近最少使用的数据,可以直接淘汰。

(1)普通的LRU链表

新加载的数据放到链表的头部,再次在缓存中读取的数据重新加入头部。那么头部数据永远是最新最热的数据,链表尾部的数据就是冷数据,可以被淘汰。

(2)划分区域的LRU链表

Innodb将LRU链表划分为了两个部分,分别是young区域和old区域。young区域在链表前端,表示最新最热数据,old区域在链表后端,表示冷数据,可以被淘汰。

young区域和old区域组成了整个LRU链表。其中old区域占用LRU链表的比例可以通过innodb_old_blocks_pct系统变量来控制,默认是37,即old区域占LRU链表的37%,young占用63%。

(3)划分区域的LRU链表的使用方法

当有新的缓存页加入时,先将其加入old链表的头部,如果没有下次访问的话,它是不会被放入young链表的。当在innodb_old_blocks_time间隔后再次访问这个缓存页,说明访问这个缓存页比较频繁,那么会将这个缓存页放入young链表的头部。

当有新的缓存页加入时,如果此时free链表是空的,说明没有空闲的缓存页了,那么就从old链表的尾部开始,淘汰掉old链表尾部的非脏页,如果都是脏页,那么会先将脏页写入磁盘。

(4)划分区域的好处

划分区域可以防止非常多的且使用频率不高的页同时加载到buffer pool中,将真正的热数据给挤到链表末尾被淘汰。导致缓存的命中率不高。

因为innodb预读机制的存在,加载到内存中的数据页不一定会用到,防止这些数据页污染LRU热数据链表。

11.6、脏页的刷新

脏页是在内存中修改过数据的页,需要刷新到磁盘上。innodb有专门的后台线程去刷新buffer pool上的脏页。刷新方式有:

(1)BUF_FLUSH_LRU

后台线程会从LRU链表的尾部扫描一些脏页,然后刷新到磁盘,这种刷新方式称为BUF_FLUSH_LRU

(2)BUF_FLUSH_LIST

脏页有自己的flush链表,后台线程会从这个链表中找到脏页,刷新到磁盘,这种刷新方式称为BUF_FLUSH_LIST

(3)BUF_FLUSH_SINGLE_PAGE

用户线程在从磁盘上读取页时,准备将此页放入buffer pool中。而此时free链表中没有空闲页,且LRU尾部的页全是脏页,那么用户线程会从LRU链表中刷新一个脏页到磁盘中,这种刷新方式称为BUF_FLUSH_SINGLE_PAGE

11.7、多Buffer pool实例和chunk

buffer pool实例可以设置多个,系统参数为innodb_buffer_pool_instances。

每个buffer pool实例中都有多个chunk,设置chunk的目的是为了方便buffer pool的扩容,扩容时,只需扩容chunk大小的整数倍即可。

chunk的大小通过系统参数innodb_buffer_pool_chunk_size指定,默认128M,和innodb_buffer_pool_size默认值一样。也就是说默认buffer pool里只有一个chunk。

11.8、查询buffer pool的状态信息

SHOW ENGINE INNODB STATUS;

(1)Buffer pool size

缓存池的页面数

(2)Free buffers

空闲缓存页面数

(3)Database pages

LRU链表中的页面数

注:因为缓存池中的页还可能分配给自适应哈希索引、Lock信息、Insert Buffer等页,所以Database pages + Free buffers小于Buffer pool size

(4)Old Databases pages

LRU链表中old区域的页面数

(5)Modified db pages

脏页的页面数,也就是flush链表的页面数

(6)Buffer pool hit rate

缓存命中率,是个关键指标,通常不低于95%

information_schema.INNODB_BUFFER_POOL_STATS表中也有buffer pool的相关信息。

11.9、page made young、page made not young

当old区域中的页被再次访问时,如果再次访问的时间间隔小于innodb_old_blocks_time值的话,那么这个缓存页不会被加入young区域,这个操作为page made not young,innodb会记录他的次数。

如果old区域的缓存页被加入到了young区域,这个操作被称为page made young。

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP