Innodb 的buffer pool

Innodb 的buffer pool

1、buffer pool的由来

在innodb存储引擎中,数据是以页为单位,存储在表空间中的,而表空间只不过是对一个或者几个实际文件的抽象,也就是说数据最终是存储在磁盘上的。
而磁盘的访问速度慢,而且innodb存储引擎访问磁盘中的数据时是以页为单位访问的,即使仅仅读取一条数据,也需要将这个数据所在的页全部加载进内存。
为了提升性能,innodb引入了类似缓存的一种结构,叫做buffer pool,将热点数据缓存起来,然后按照一定的淘汰策略进行淘汰,这样在读取时如果命中缓存,则不用访问磁盘,可以大幅度提升性能。

2、buffer pool的组成

buffer pool中的结构也是按照页来进行组织的,这样可以将磁盘中的页读进来,然后存储在buffer pool中的页中,这些页也称为缓存 页。因为buffer pool的空间一般很大,可以通过 show variables like 'innodb_buffer_pool_size';来查看具体的大小,为了方便管理如此多的缓存页,由引入了控制块这么一个结构,每个缓存页都有与之对应的控制块,控制块中记录了该缓存页所缓存的物理页的表空间号,页号,在buffer pool中的位置信息…,整体结构类似下面这个图:
在这里插入图片描述

3、buffer pool管理

如何知道一个页在不在buffer pool中呢?其实innodb时根据表空间号 + 页号来定位一个页的,也就相当于表空间号 + 页号是一个 key,缓存页就是对应的 value,表空间号 + 页号作为 key,缓存页作为 value 创建一个哈希 表,在需要访问某个页的数据时,先从哈希表中根据表空间号 + 页号看看有没 有对应的缓存页,如果有,直接使用该缓存页就好,如果没有,那就从 free 链 表中选一个空闲的缓存页,然后把磁盘中对应的页加载到该缓存页的位置。然后更新这个hash结构。

3.1、free 链表的管理

启动mysql服务器的时候,需要对buffer pool进行初始化,分配需要的内存空间,并将其划分为缓存页和控制块。为了方便管理,也就是说可以方便的拿到空闲页以及方便的管理非空闲页,将整个buffer pool中的缓存页进行了划分,这样可以方便管理。由空闲的控制块组成的链表称为free 链表。
在这里插入图片描述

当执行第一个查询的时候,此时因为缓存中还没有数据,因此从磁盘中获取一个数据页加载进来,只需要从空闲链表中获取一个空闲页,然后对控制块中的数据进行修改,然后从free 链表中进行移除,这样就表明这个缓存页已经被使用了。

3.2 LRU链表的管理

内存不是无限大的,当数据达到一定多的时候,必须将一部分数据淘汰掉,对于缓存这种淘汰策略最典型的就是LRU,最近最少使用。典型的LRU淘汰策略,就是将最近使用的节点添加到链表的头部,这样尾部的自然会被淘汰掉。但是针对Mysql一些特殊场景,mysql对这个LRU进行了改善。

  • 预读机制:mysql在读取一个页时,会把其附近的页也会读进来,而且如果读取的页超过了指定的阈值,则会将这个区的所有页面加载进来。其实很多数据一时半会是不会使用的。但是这样又占据了LRU很大一部分内存。
  • 执行全表扫描的语句。如果数据很多,此时在传统的LRU链表中,会对整个LRU链表进行替换。

为了解决上述场景所带来的问题:
mysql将LRU链表分为两部分,一部分存储使用频率很高的页,一部分存储使用频率不是很高的页,当有新的页进入LRU链表时,并不直接添加到LRU的头部,而是放到old区域的头部,这样针对预读 / 全表扫描 进来的页并不会把频繁使用的页挤出去。因为刚加载进来的页紧接着就要读数据,为了避免直接被移动到头部,又引入了一个时间间隔控制,只有在连续的两次访问的时间间隔小于这个时间,才会将这个页移动到链表的头部。SHOW VARIABLES LIKE 'innodb_old_blocks_time';
在这里插入图片描述

3.3 flush 链表的管理

flush链表用来管理被修改的页,被修改的页称之为脏页,脏页即存在于Lru链表中同时也存在于flush链表中。将脏页的控制块链接在一起形成的链表称为flush 链表。
当一个数据要进行修改时,先在buffer pool中进行修改,然后由后台线程将脏页刷新的磁盘中。当然flush 链表和lru链表最终指向的页是一样的。
那么什么时候刷新呢?最简单的就是每修改一次就刷新一次,但是这样涉及大量随机IO,性能 太差。因此会采取后台线程定时刷新的方式进行刷新,而且在刷新时,如果检测该脏页所在的区还有脏页,会将这些脏页也进行刷新。

4、多个buffer pool

为了提升并发性能,引入多个buffer pool,这样多个buffer pool直接的读写操作无需同步,可以大幅提升读写性能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值