MySQL: 14 LRU链表在Buffer Pool实际运行中可能导致的问题

1. LRU链表在Buffer Pool的应用

Buffer Pool在使用过程中如果缓存页都使用了,没有空闲的缓存页时,可以去LRU链表中的尾部找一个最近最少使用的缓存页,把它的数据刷入磁盘,腾出来一个空闲缓存页,然后加载需要的新的磁盘数据页到空闲缓存页里去。

LRU链表的机制,只要是刚从磁盘上加载数据到缓存页里去,这个缓存页就放入LRU链表的头部,后如果对任何一个缓存页的访问,都会把缓存页从LRU链表中移动到头部去。

这样在LRU链表的尾部,一定是最近最少被访问的那个缓存页。

2.LRU机制在实际运行中存在的隐患

首先会带来的隐患是MySQL的预读机制,说的就是当你从磁盘上加载一个数据页的时候,他可能会把这个数据页相邻的其他数据页,也加载到缓存页里去。

举个例子,假设现在有两个空闲缓存页,然后在加载一个数据页的时候,连带着把它的一个相邻的数据页也加载到缓存里去了,正好每个数据页放入一个空闲缓存页。

实际上这里只有一个缓存页是被访问了的,另外一个通过预读机制加载的缓存页,并没有人访问,但由于LRU机制导致两个缓存页都在LRU链表的前面。

 参照上图,假如没有空闲缓存页了,那么此时要加载新的数据页了,就需要从LRU链表的尾部把所谓的“最近最少使用的一个缓存页” 给拿出来,刷入磁盘。

这时候有个问题,那就是如果把上图中LRU尾部的那个缓存页刷入磁盘然后清空,那这是不合理的,因为它之前一直频繁被人访问,只不过在这一瞬间,被新加载进来的两个缓存页给占据了LRU链表前面的位置,尤其是第二个缓存页,它是通过预读机制加载进来的,并没有人去访问。

最合理的应该是把上图中LRU链表的第二个通过预读机制加载进来的缓存页给刷入磁盘和清空,因为它几乎没有被访问过。

3.触发MySQL预读机制的场景

触发MySQL预读机制的情况有以下几种:

(1)有一个参数是 innodb_read_ahead_threshold,它的默认值是56,意思是如果顺序的访问了一个区里的多个数据页,访问的数据页的数量超过了这个阈值,此时就会触发预读机制,把下一个相邻区中的所有数据页都加载到缓存里去。

(2)如果Buffer Pool里缓存了一个区里的13个连续的数据页,而且这些数据页都是比较频繁会被访问的,此时就会直接触发预读机制,把这个区里的其他的数据页都加载到缓存里去。

预读机制是通过参数 innodb_random_read_ahead 来控制的,它默认是OFF,也就是说这个规则是默认关闭的。

默认情况下,主要是第一个规则可能会触发预读机制,一下子把很多相邻里的数据页加载到缓存里去,这些缓存页如果一下子都放在LRU链表的前面,而且没有什么人访问的话,就会导致原来在缓存里的一些频繁被访问的缓存页在LRU链表的尾部。

从而导致这部分频繁被访问的缓存页给刷入磁盘和清空掉。

4. 全表扫描导致频繁被访问的缓存页被淘汰的场景

另外一种可能导致频繁被访问的缓存页被淘汰的场景,那就是全表扫描。

所谓全表扫描,就是类似如下的SQL语句: SELECT * FROM USERS。这种语句没加任何一个where 条件,导致一下子把该表中所有的数据页,都从磁盘加载到Buffer Pool里去。

在全表扫描的场景下,会一下子把这个表的所有数据页都一一装入各个缓存页里去。此时可能LRU链表中排在前面的一大串缓存页,都是全表扫描加载进来的数据页。

这就会导致这次全表扫描过后,排在LRU链表头部的是几乎没用到的表里的数据的缓存页。

而在LRU链表的尾部,可能全都是之前一直被频繁访问的那些缓存页。

然后当你要淘汰一些缓存页腾出空间时,就会把LRU链表尾部一直被频繁访问的缓存页给淘汰掉了,而留下之前全表扫描加载进来的大量的不经常访问的缓存页。

5.总结

在使用简单的LRU链表机制时,由于预读机制或全表扫描的机制,会导致一下子把大量未来可能不怎么访问的数据页加载到缓存里去,然后LRU链表的前面全部是这些未来可能不怎么被访问的缓存页。

而真正之前一直被频繁访问的缓存页可能都在LRU链表的尾部。

如果没有空闲缓存页的时候,就会导致把LRU链表尾部那部分频繁被访问的缓存页刷入磁盘、清空掉,以此来腾出空间。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值