Buffer Pool

总结一下MySQL中的Buffer Pool

1. 磁盘速度非常慢,而CPU的速度非常快。所以磁盘和CPU之间加了一道Buffer Pool。将磁盘中的数据先加载到Buffer Pool中(将磁盘页加载到Buffer Poll的缓存页中),Buffer Pool是在内存空间申请的一块连续的内存空间。

2. Buffer Pool的数据格式是: 每一个控制块对应一个缓存页,由这些控制块和缓存页组成,可能还会有碎片(因为没有足够的空间分配控制块和缓存页)

3. 为了区分哪一些缓存页是空闲的哪一些缓存页不是空闲的,维护了一个Free双向链表。 并且链表维护了一个头结点,头结点中保存的是首部结点和尾节点的位置,还有就是链表中的节点个数,该头结点并不属于Buffer Pool申请的连续空间中,而是处于独立的空间。节点是控制块,因为控制块对应着缓存页。

4. 如果Buffer Pool缓存页中的数据更改了,而没有同步到磁盘中,那么该页便成了脏页。Buffer Pool为了维护哪些页中的数据改了,而维护了一个Flush双向链表,结构是同Free链表结构一样,但是该链表中的节点表示的是哪些控制块对应的数据页中的数据被更改了。

5. 如果我们要访问某个页中数据(Innodb管理的是页,数据存在页中),需要将该页加载到Buffer Pool中,那么如果该页已经在Buffer Pool中的话就可以直接使用,但是我们怎么知道该页是不是在Buffer Pool中呢?其实想想每个页的定位是 表空间 + 页号 ,而该页对应的应该放在哪个缓存页中,所以可以利用哈希表来完成。key保存的是表空间 + 页号,而value对应的是缓存页。

6. 缓存需要面对的一个问题就是缓存满了,没有足够的空间的问题。Buffer Pool中利用的是LRU算法的思想,维护一个LRU双向链表,淘汰掉链表尾部的节点,也就是最近最少使用的节点。

7. Innodb中的预读:Innodb认为执行当前的请求可能会访问某些页面,就预先将某些页面加载到Buffer Pool中。预读可以分为线性预读和随机预读。预读可能存在的问题:将预读的数据加载到了Buffer Pool中,但是这些页并没有访问,而将其他页的数据给淘汰掉了。 为了解决这个问题,Innodb给LRU链表做了优化,按某种比例将其分为young区和old区。young区域存储的是使用频率高的数据,old区存放的是使用频率低的数据。当磁盘中数据页初次加载到Buffer Pool中的时候,优先分配在old区的头部,如果后续不会使用到将会移动到链表的尾部淘汰掉。

8. 而针对全表扫描,短时间访问大量使用频率低的页面的情况,将所有的数据加载到Buffer Pool中,分配在old区头部,访问的时候将他移动到young头部,那么这样同样会出现使用频率低的将高频的数据挤掉的情况。针对这种情况,在控制块记住第一次访问的时间,如果在第二次访问和第一次访问的时间间隔超过了某个值的时候就不将该数据移动到young区头部

9. 对于young中的数据都是热数据,然后每次访问一个热数据就让他移动到头部似乎不太好,因为都是热数据,频繁的移动性能不好。那么可以这样:如果访问的是young区的前1/4的数据时,不会移动到头部,而后面3/4的数据才会移动。

10. 将脏页刷新到磁盘的时候会有专门的后台线程去处理,可以有两种:1)从LRU old区域中刷新一部分到磁盘 2)从flush中刷新一部分到磁盘中

猜你喜欢

转载自www.cnblogs.com/lgxblog/p/11691486.html