MySQL —— 缓冲池 Buffer Pool

。_饼干妹妹 提交于 2021-02-04 09:39:57

本文主要内容源自官网:https://dev.mysql.com/doc/refman/8.0/en/innodb-buffer-pool.html

感兴趣的可以直接阅读

缓冲池是主内存的一块区域,在 InnoDB 访问表和索引数据时会在其中进行高速缓存(可以联系 CPU 的高速缓存)。在专用服务器上,通常会把 80% 的内存分配给缓冲池。

缓冲池被分为多个页面,这些页面可能包含多个行。缓冲池使用列表数据结构。使用 LRU (Least Recently Used,最近最少使用)算法的变体将数据从缓存中老化。

缓冲池 LRU 算法

缓冲池 LRU 算法将缓冲池作为列表进行管理。当缓冲池空间不足,但有新页面需要添加到缓冲池时,将驱逐最近最少使用的页面,并将新页面添加到列表的 Midpoint(中点)。总列表分为两个子列表(Sublist):

1. 最前面的是最近访问过的新页面(或者叫 young 页面,年轻页面)子列表

2. 末尾是最近访问的旧页面的子列表

 

该算法将经常需要访问的页面保留在 New Sublist。Old Sublist 包含不常用的页面,这些页面是驱逐的候选对象。

通常情况,该算法遵循以下规则:

1. \frac{3}{8} 的 Buffer Pool 用于 Old Sublist

2. 列表的 Midpoint 是 New Sublist 的 Tail 和 Old Sublist 的 Head 相交的边界。

3. 当 InnoDB 将页面读入缓冲池时,它首先将页面插入 Midpoint。通过用户触发的动作(比如 SQL 查询)或者预读操作可以对页面进行读取。

注意:官方这里说的读取(read)并不代表访问(access),请看下面。

4. 访问(access)Old Sublist 中的页面会让其变得 young,然后将其移至 New Sublist 的 Head。如果是因为用户触发的动作需要读取页面,则将立即进行第一次 access,使页面 young。如果使由于预读操作而读取了该页面,则第一次 access 不会立即访问,甚至在页面离开之前都不会发生

注意:预读未必会让页面变 young。

5. 随着数据库的运行,通过将页面移动到列表的尾部,缓冲池中的页面将会“老化”。New 和 Old Sublist 都会随着其他页面的更新而老化。随着将页面插入 Midpoint,旧子列表中的页面也会老化。最终,未使用的页面到达子列表的尾部并被逐出。

注意:这里有个有趣的现象,页面是先插入到 Midpoint,而且这些页面插入之后属于 Old Sublist 的范围,所以他们很可能会马上“老化”,唯一让他们变得 young 的途径就是 access 一次。

 

默认情况下,查询(Query)读取的页面会立即移入新的子列表,这意味着它们在缓冲池停留的时间更长。

举个例子,mysqldump 操作或者 SELECT 不带 WHERE 子句的语句可能会将大量数据带入缓冲池,并驱逐出相当多的旧数据,即使加入 New Sublist Head 的新数据可能都不会再被使用了。同样,预读线程加载的页面,且仅仅访问过一次,那么也会移至 New Sublist 的开头。这些情况可能会将常用页面推到旧的子列表,然后被逐出。

所以,这似乎有个问题,有些页面命名使用的频率不如其他页面,却可以插在其他页面前面,甚至逐出其他页面 ,官方给出了优化此行为的方法:让缓冲池的扫描具有“抵抗力”配置 InnoDB 缓冲池预读(具体见官网)。

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!