天天看点

InnoDB之缓冲池

资源来自:《MySQL技术内幕 InnoDB存储引擎》

一.缓冲池

我们都知道InnoDB是基于磁盘存储的,如果直接面向磁盘读取查询和插入数据的是很消耗IO资源的,同时效率也很不理想。在该类型数据库系统中,CPU速度与磁盘之间的存在很大的差距,而缓冲池技术能够缩短这种差距,提高数据库的整体性能。
   缓冲池:一块内存区域,通过内存的速度来弥补磁盘速度慢对数据库的影响。在数据库中进行读取页的操作,首先将从磁盘中读取到的页存放在缓冲池中,下一次再读取到相同的页时,首先判断该页是否在缓冲池中,如果有,直接从内存中读取即可,如果没有,再去访问磁盘。
   对于数据库中的页的修改,会首先修改缓冲池中的页,然后以一定的频率刷新到磁盘中。注意:*页从缓冲池刷新到磁盘的操作并不是每次页发生更新时,触发的,而是通过Checkpoint机制刷新到磁盘的(该技术会在后面文章中讲到)*。缓冲池可以通过参数:**innodb_buffer_pool_size**设置,通过使用指令                      ***SHOW  VARIABLES  LIKE  'innodb_buffer_pool_size'\G***。
   缓冲池中缓存的数据页类型由:索引页、数据页、undo页、插入缓冲(insert buffer)、自适应哈希索引(adaptive hash index)、InnoDB存储的锁信息(lock info)、数据字典信息(data dictionary)等。缓冲池中缓存索引页和数据页占很大一部分,但是不能说:缓冲池只是缓存索引页和数据页。
   缓冲池的实例数量:InnoDB 1.0X 版本开始,允许有多个缓冲池实例,通过哈希值平均分配到不同的缓冲池实例中。多例的作用:减少数据库内部的资源竞争,增加数据库的并发处理能力,可以通过参数**innodb_buffer_pool_instances**进行配置,默认值为1,可以通过指令**SHOW ENGINE INNODB STATUS**观察INNODB存储引擎的当前运行情况。
   从MySQL5.6开始,可以通过information_scherma架构下的表**INNODB_BUFFER_POOL_STATS**来观察缓冲额状态,例如:
   SELECT POOL_ID,POOL_SIZE,FREE_BUFFER,DATABASE_PAGES FROM INNODB_BUFFER_POOL_STATS\G
           

二.缓冲池的管理

通常数据库中的缓冲池是通过LRU(Lastest Recent Used,最近少使用)算法来管理缓冲池。在该算法中,将使用最频繁的页放在LRU列表的最前端,使用最少的放在LRU列表的尾端,当缓冲池不能存放新的页时,将首先释放掉LRU列表中的尾端的页。
           
INNODB中的LRU算法
在其基础之上又加入了midpoint位置,该位置用来存放新读取到的页数据,当读取到新的页数据时,不回将其放在LRU列表的首端,而是放在midpoint位置。该算法在INNODB中被称为:midpoint insertion strategy,默认情况下midpoint位置是在LRU列表的5/8处,当然也可通过设置参数innodb_old_blocks_pct来改变midpoint的在LRU列表中的位置,例如将midpoint设置为:37,midpoint位置就在LRU列表的尾部37%的位置,在INNODB将midpoint位置之前的列表成为new列表,midpoint之后的列表成为old列表,new列表中的页都是比较活跃的热点数据。
LRU列表用来管理已经读取的页,当数据库刚启动时,LRU列表时空的,此时所有的空页都在Free列表中,当需要在缓冲池中分页的时候,先判断该Free列表黄总是否还存在空页,如果有的话,就将该页从Free列表中三处吧,放入LUR列表中。
从LRU的old部分加入到new列表时,称此时发生的操作为:page made young ,而因为innodb_old_blodb_time的设置而导致old部分移动到new 部分的操作称为:page not  made  young ,通过Show engine innodb  states来观察LRU列表以及Free列表的使用情况。
Buffer  pool  size   :  缓冲池的大小 , 单位:页
Free  buffers  :  当前列表中的数量,Database   pages数量之和不好等于buffer  pool  size
           
设置midpoint位置的原因

**:某些操作访问的页会很多,那么返回的页数据会很多,如果返回页的数量足够充满LRU列表或者覆盖new列表的话,此时将返回的页数据放在LRU列表的首端,只能通过移除LRU中的热点数据,给此时的返回页腾出地方,之后再访问热点数据的时候,需要再次访问磁盘,无疑这样会增加磁盘的IO流,影响缓冲池的效率。

另外,INNODB还引入了另一个参数:innodb_old_blocks_time,用于表示:读取到的midpoint位置的页,需要等待多久才会被加入到LRU的热端。

Checkpoint技术

作用:

数据库为了较高性能,采用缓冲池来协调磁盘和CPU之间鸿沟,所以也得操作首先是在缓冲池中开始的。所以,当Update和Delect改变了页数据时,缓存中的数据是脏的,因为缓冲池的数据比磁盘中的数据要新,两者数据不一致,数据库需要将新版本的页刷新到磁盘中。

现在问题来了,如果每一次缓冲池中的页被修改都将业新页刷新到磁盘中,刷新的频率是很高的,开销很大。Checkpoint技术的作用就是将缓冲池中的脏页刷新到磁盘中。

为了避免数据丢失,当前事务数据库普遍采用Write Ahead Log策略,即当事务提交时,先写重写日志,再修改页。当发生宕机的时候,可以通过重做日志来恢复数据。

前面讲过LRU列表,如果当列表资源不够用时,会移除列表中最少用的页,而如果被移除的页是一个脏页,那么就需要将该页刷新到磁盘中,此时用到Checkpoint技术。

另外,前面说过,在对缓存池中的页进行删改之前会先记录操作日志到重做日志中,而如果重做日志文件不可能是无限的,如果当日志的数量到达了重做日志的阀值,又将怎么办?此时需要使用,checkpoint技术将脏页刷新到磁盘中。即便重做日志可以无限存储,那么当数据库宕机后实行数据恢复时,恢复时间也是一个问题,数据的日积月累,恢复起来势必会花费很长时间,至于需要多长时间是无法预估的。

综上:Checkpoint技术的作用是为了解决一下问题:

缩短数据库的恢复时间

缓冲池不够用时,将脏页刷新到磁盘

重做日志不用时,刷新脏页

宕机时,只需重做Checkpoint之后的页刷新到磁盘中,而不需要将所有的页刷新到磁盘,大大提高了数据库的性能。

InnoDB中支持两种Checkpoint工作方式:

Sharp Checkpoint : 将所有的脏页刷新到磁盘(数据库关闭时使用,默认)

Fuzzy Checkpoint :只刷新一部分脏页到磁盘(InnoDB运行时使用)

继续阅读