Buffer Pool 简介


执行增删改操作时,直接更新到磁盘随机读写操作速度慢,大磁盘文件的随机读写操作可能都要几百毫秒。在对数据库增、删、改操作时,实际上主要都是针对内存里的Buffer Pool中的数据进行的,如下图所示:
Buffer Pool(缓冲池) - 图1
当内存中先更新数据页与磁盘不一致叫脏页,更新数据页到磁盘称之为刷脏页。
如果数据库突然崩溃内存中的新数据页没有刷新到磁盘会通过redo log去恢复

Buffer Pool 内存空间


InnoDB为每一个缓存页控制信息包括该页所属的表空间编号、页号、缓存页在缓冲池中的地址、链表节点信息、一些锁信息。每个页对应的控制信息占用的一块内存称为一个控制块,控制块和缓存页是一一对应的,所以整个Buffer Pool对应的内存空间看起来就是这样的:
Buffer Pool(缓冲池) - 图2

free 链表


启动MySQL服务器时,此时并没有真实的磁盘页被缓存到缓冲池中,之后随着程序的运行,会不断的有磁盘上的页被缓存到缓冲池中。从磁盘上读取一个页到缓冲池中的时候该放到哪个缓存页的位置呢?
思路:区分缓冲池中哪些缓存页是空闲的,哪些已经被使用了。
把所有空闲的缓存页对应的控制块作为节点放到一个链表中,这个链表叫作 free 链表。

flush 链表


如果修改缓冲池中某个缓存页的数据,磁盘上的页不一致了,这样的缓存页也被称为脏页(dirty page)。
Innodb 创建了一个存储脏页的链表,凡是修改过的缓存页对应的控制块都会作为一个节点加入到一个链表中,在未来的某个时间点进行同步。这个链表叫做 flush 链表。
Buffer Pool(缓冲池) - 图3

LRU 链表


Buffer Pool的内存大小是有限的,当内存不足时会采用LRU算法淘汰缓存中的非脏数据页,LRU链表分为young和old两个区域,可以通过innodb_old_blocks_pct来调节old区域所占的比例。首次从磁盘上加载到Buffer Pool的页会被放到old区域的头部,在innodb_old_blocks_time间隔时间内访问该页不会把它移动到young区域头部。在Buffer Pool没有可用的空闲缓存页时,会首先淘汰掉old区域的一些页。
Buffer Pool(缓冲池) - 图4

(详见:https://juejin.cn/book/6844733769996304392/section/6844733770063429646)