16 简单的LRU链表在Buffer Pool实际运行中,可能导致哪些问题?
1.预读会带来一个巨大的问题?
预读机制也就是从磁盘加载一个数据页的时候,也可能连带着把这个数据页相邻的其他的数据页也加载到缓存里去
举个例子,假设现在有两个空闲页,然后在加载数据页的时候也顺带把他相邻的数据页也加载到缓存里,正好每个数据页放一个空闲的缓存页,但是接下来呢,实际上只有一个缓存页被访问,另外一个被预加载的缓存页没人访问,此时这两个缓存页都在LRU的前面,这时缓存页已经满了,但是需要把LRU链表后边的刷到磁盘,但是目前LRU链表后边的这个数据是经常被访问的,而这个被预加载的缓存页却排在了它前面,这样就不太合理
2.哪些情况下会触发Mysql的的预读机制?
(1)一个参数innodb_read_ahead_threshold,他的默认值是56,意思就是如果顺序的访问了一个区里的多个数据页,访问的数据页数量超过这个阈值,此时就会触发预读机制,把下一个相邻区中的所有的数据页都加载到缓存里去
(2)如果Buffer Pool里缓存了一个区里的13个连续的数据页,而且这些数据页都是比较频繁会被访问的,此时就会
直接触发预读机制,把这个区里的其他的数据页都加载到缓存里去
这个机制是通过参数innodb_random_read_ahead来控制的,他默认是OFF,也就是这个规则是关闭的
所以默认情况下,主要是第一个规则可能会触发预读机制,一下子把很多相邻区里的数据页加载到缓存里去,这些缓
存页如果一下子都放在LRU链表的前面,而且他们其实并没什么人会访问的话,那就会如上图,导致本来就在缓存里
的一些频繁被访问的缓存页在LRU链表的尾部。
3.另外一种可能导致频繁被访问的缓存页被淘汰的场景
全表扫描:比如 select*from user
他没加任何一个where条件,会导致一下子把这个表的所有的数据页,从磁盘加载到Buffer Pool 里去,这时候可能会把所有的这些数据页都装入到缓存页去,如果此次全表扫描的数据以后都不用了呢,但是他都排在了LRU链表的前面,后边的数据是一直都频繁使用的,这时缓存页已经满了,再加载数据页到缓存页要把LRU链表后边的缓存页清理,这时就不合理了