天天看点

MySQL技术内幕:InnoDB存储引擎之缓冲池技术(内存管理)——详解InnoDB存储引擎之缓冲池原理

InnoDB存储引擎之缓冲池原理

对于InnoDB存储引擎体系架构不清楚的朋友可以看看这篇博客:

MySQL—InnoDB存储引擎体系架构——详解

1.缓冲池概述

  • InnoDB存储引擎是基于磁盘存储的,将其中的记录按照页的方式进行管理,因此可以将其看做基于磁盘的数据库系统。但是在数据库系统中,由于CPU速度与磁盘速度之间的鸿沟,基于磁盘的数据库系统通常使用缓冲池技术来提高整体性能(因为与CPU IO和与磁盘 IO的速度差距非常大)
  • 缓冲池简单来说就是一块内存,通过访问缓冲池来进一步访问磁盘,弥补磁盘速度较慢的影响。
  • 在数据库读取页的操作时,首先判断该页在不在缓冲池中,如果不在那就首先将该页从磁盘读取到缓冲池中,然后在缓冲池中进行查询等。下次读相同页的时候,就只需要在缓冲池中读取即可(前提是该页还在缓冲池内,也有可能被移除了)。
  • 对于数据库页的修改操作,则首先修改在缓冲池中的页,修改页但是此时还没有刷新回磁盘,称为脏页。InnoDB并不是修改之后立即刷新回磁盘,而是以一定的频率和机制刷新回磁盘,这种触发机制成为CheckPoint(后面会更新CheckPoint的文章)

2.缓冲池组成

  • 缓冲池共有六部分组成:

    1)数据页

    2)索引页

    3)插入缓冲

    4)锁信息

    5)自适应哈希索引

    6)数据字典信息

  • 在缓冲池中,数据页和索引页占了很大一部分
  • 从InnoDB 1.0.x版本开始,允许有多个缓冲池实例。每个页根据哈希值平均分配到不同缓冲池实例中。这样做的好处就是减少数据库内部的资源竞争,增加数据库并发处理的能力。
  • 对于插入缓冲,是InnoDB关键特性之一,可以单独看这篇文章:

    InnoDB存储引擎关键特性之插入缓冲——详解

MySQL技术内幕:InnoDB存储引擎之缓冲池技术(内存管理)——详解InnoDB存储引擎之缓冲池原理

3.缓冲池的内存管理机制

  • 我们现在知道了缓冲池是一块很大的内存区域,其中存放各种类型的页。那么InnoDB对这块内存是如何进行管理的呢?

3.1 LRU List

  • 通常来说,数据库中的缓冲池是通过LRU(Latest Recent Used, 最近最少使用)算法来进行管理的。
  • 即最频繁使用的页放在LRU列表的前端,最少使用的页放在LRU列表的尾端,当缓冲池中不能存放新读取的页时,就首先释放LRU列表中的尾端的页。

InnoDB中存储引擎中对LRU算法进行了一些优化:

  • InnoDB在LRU列表中引入了midpoint参数。新读取的页并不会直接放在LRU列表的首部,而是放在LRU列表的midpoint位置。在默认配置下,这个位置在LRU列表的5/8处,我们将mid之前称为热端(热点数据),mid之后称为冷端
  • InnoDB还引入了innodb_old_blocks_time参数,即当新页放在midpoint上之后,必须过了等待这么久的时间后如果还存活在LRU列表上,才可以被调到热端上。

优化的原因:

  • 为什么引入midpoint参数呢?因为有可能这次读取的新页仅仅是在这次sql操作查询中需要用到,并且之后用到的概率非常小,如果把这样的页直接放在LRU列表的首部,那么就可能会将比其更加热点的页移到后面甚至是移除LRU列表
  • 为什么引入innodb_old_blocks_time参数?针对于某些sql操作,这些操作可能会访问表中的许多页,甚至是全部的页。那么这些页也仅仅是在这次查询中要用到,并不是活跃的热点数据,所以设置一个等待时间,如果过了这个等待时间,这些页还存活在缓冲池中的话,才可以被移动到热端。

3.2 Free List

  • LRU列表用来管理已经读取的页,但当数据库刚启动的时候,LRU列表是空的,即没有任何的页。这时页都存放在Free List中。
  • 当需要从缓冲池分页时,首先从Free列表中查找是否有可用的空闲页,若有则将该页从Free列表中删除,放入LRU列表中。 否则根据LRU算法,淘汰LRU列表尾端的页,将内存空间分配给新的页
  • 注意的就是:缓冲池中的页还可能被分配给自适应哈希索引,锁信息,插入缓冲页等,这部分的页不在LRU列表中,不需要LRU算法进行维护

3.3 Flush List

  • 在LRU列表中被修改的页,称为脏页,即缓冲池中的页和磁盘上的页数据产生了不一致,这时候数据库会通过CheckPoint机制将脏页刷新回磁盘。
  • Flush列表中的页即为脏页列表。需要注意的是,脏页即存在于LRU列表中,也存在与Flush列表中

3.4 LRU对压缩页的管理

  • InnoDB存储引擎从1.0.x版本开始支持压缩页的功能,即将原本16KB的页压缩为1KB,2KB,4KB,8KB
  • 由于页的大小变化,LRU列表也有了些许的改变。对于非16KB的页,是通过unzip_LRU列表进行管理的

unzip_LRU列表的内存管理: 通过 伙伴算法 实现不同压缩页大小的管理

  • 例如需要从缓冲池中申请页为4KB大小,过程如下:

    1)首先检查4KB的unzip_LRU列表是否有可用的空闲页

    2)若有,则直接使用

    3)若没有则检查8KB的unzip_LRU列表是否有可用的空闲页

    4)如果有,则将一页分为两个4KB的页,然后存放到4KB的unzip_LRU列表中

    5)如果没有,则从LRU列表中申请16KB的页,将其分为一个8KB,两个4KB的页去分配

4.总结

  • 缓冲池的内存管理最关键的就是LRU列表的实现!以及其对LRU算法的优化设计,引入的两个参数