缓冲池是主内存中的一个区域,在
InnoDB
访问时缓存表和索引数据。缓冲池允许直接从内存访问频繁使用的数据,从而加快处理速度。在专用服务器上,通常会将高达 80% 的物理内存分配给缓冲池。
为了提高大容量读取操作的效率,缓冲池被分成可能包含多行的页面。为了缓存管理的效率,缓冲池被实现为页面链表;很少使用的数据使用最近最少使用 (LRU) 算法的变体从缓存中老化。
知道如何利用缓冲池将频繁访问的数据保存在内存中是 MySQL 调优的一个重要方面。
缓冲池使用 LRU 算法的变体作为列表进行管理。当需要空间将新页面添加到缓冲池时,最近最少使用的页面将被逐出,并将新页面添加到列表的中间。这种中点插入策略将列表视为两个子列表:
在头部,最近访问 的新( “年轻” )页面的子列表
在尾部,最近较少访问的旧页面的子列表
该算法将经常使用的页面保留在新的子列表中。旧的子列表包含不常用的页面;这些页面是驱逐的候选者。
默认情况下,算法运行如下:
缓冲池的 3/8 专门用于旧子列表。
列表的中点是新子列表的尾部与旧子列表的头部相交的边界。
当
InnoDB
将页面读入缓冲池时,它最初将其插入到中点(旧子列表的头部)。可以读取一个页面,因为它是用户启动的操作(例如 SQL 查询)所必需的,或者作为 由 自动执行的预读操作的一部分InnoDB
。访问旧子列表中的页面使其成为 “新”页面,将其移动到新子列表的头部。如果页面是因为用户启动的操作需要它而被读取的,则第一次访问会立即发生并且该页面成为新页面。如果页面是由于预读操作而被读取的,则第一次访问不会立即发生,并且在页面被逐出之前可能根本不会发生。
随着数据库的运行,缓冲池中未访问的页面通过向列表的尾部移动而“老化” 。随着其他页面的更新,新旧子列表中的页面都会老化。随着在中点插入页面,旧子列表中的页面也会老化。最终,未使用的页面到达旧子列表的尾部并被逐出。
默认情况下,查询读取的页面会立即移动到新的子列表中,这意味着它们在缓冲池中停留的时间更长。例如,为mysqldump操作或
SELECT
没有子句的语句
执行的表扫描WHERE
可以将大量数据带入缓冲池并驱逐等量的旧数据,即使新数据不再使用也是如此。同样,由预读后台线程加载且仅访问一次的页面将移至新列表的头部。这些情况可以将经常使用的页面推送到旧的子列表,在那里它们会被驱逐。有关优化此行为的信息,请参阅
第 14.8.3.2 节,“使缓冲池扫描抵抗”和
第 14.8.3.3 节,“配置 InnoDB 缓冲池预取(预读)”。
InnoDB
BUFFER POOL AND MEMORY
Standard Monitor 输出在有关缓冲池 LRU 算法操作的部分中包含几个字段。有关详细信息,请参阅使用 InnoDB 标准监视器监视缓冲池。
您可以配置缓冲池的各个方面以提高性能。
理想情况下,您将缓冲池的大小设置为尽可能大的值,为服务器上的其他进程留出足够的内存来运行而无需过多的分页。缓冲池越大,就越
InnoDB
像内存数据库,从磁盘读取数据一次,然后在后续读取期间从内存访问数据。缓冲池大小是使用innodb_buffer_pool_size
配置选项配置的。在具有足够内存的 64 位系统上,您可以将缓冲池拆分为多个部分,以最大程度地减少并发操作之间对内存结构的争用。有关详细信息,请参阅第 14.8.3.1 节,“配置多个缓冲池实例”。
您可以将经常访问的数据保留在内存中,而不管来自将大量不经常访问的数据带入缓冲池的操作的活动突然激增。有关详细信息,请参阅 第 14.8.3.2 节,“使缓冲池具有抗扫描性”。
您可以控制如何以及何时执行预读请求以异步将页面预取到缓冲池中,以预期可能很快需要这些页面。有关详细信息,请参阅第 14.8.3.3 节,“配置 InnoDB 缓冲池预取(预读)”。
您可以控制何时发生后台刷新以及是否根据工作负载动态调整刷新率。有关详细信息,请参阅 第 14.8.3.4 节,“配置缓冲池刷新”。
您可以配置如何
InnoDB
保留当前缓冲池状态,以避免在服务器重启后出现冗长的预热期。有关详细信息,请参阅 第 14.8.3.5 节,“保存和恢复缓冲池状态”。
InnoDB
可以使用访问的标准监视器输出
SHOW
ENGINE INNODB STATUS
提供有关缓冲池操作的指标。缓冲池指标位于Standard Monitor 输出
BUFFER POOL AND MEMORY
部分
:InnoDB
----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 2197815296; in additional pool allocated 0
Dictionary memory allocated 155455
Buffer pool size 131071
Free buffers 92158
Database pages 38770
Old database pages 14271
Modified db pages 619
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 4, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 322, created 38448, written 42083
0.00 reads/s, 222.30 creates/s, 159.47 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead
0.00/s
LRU len: 38770, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
下表描述了
InnoDB
标准监视器报告的缓冲池指标。
Standard Monitor 输出中提供的每秒平均值InnoDB
基于自
InnoDB
上次打印 Standard Monitor 输出以来经过的时间。
表 14.2 InnoDB 缓冲池指标
姓名 | 描述 |
---|---|
分配的总内存 | 为缓冲池分配的总内存(以字节为单位)。 |
分配额外的池 | 为附加池分配的总内存(以字节为单位)。 |
字典内存分配 | 为数据字典分配的总内存(InnoDB 以字节为单位)。 |
缓冲池大小 | 分配给缓冲池的页面总大小。 |
空闲缓冲区 | 缓冲池空闲列表的页面总大小。 |
数据库页面 | 缓冲池 LRU 列表的页面总大小。 |
旧数据库页面 | 缓冲池旧 LRU 子列表的页面总大小。 |
修改后的数据库页面 | 当前在缓冲池中修改的页数。 |
待读 | 等待读入缓冲池的缓冲池页数。 |
挂起写 LRU | 从 LRU 列表底部开始写入缓冲池中旧脏页的数量。 |
挂起写入刷新列表 | 检查点期间要刷新的缓冲池页面数。 |
挂起写单页 | 缓冲池中待处理的独立页面写入数。 |
页面变得年轻 | 缓冲池 LRU 列表中年轻的页面总数(移动到“新”页面子列表的头部)。 |
页面制作不年轻 | 缓冲池 LRU 列表中未变为年轻的页面总数(保留在“旧”子列表中而未变为年轻的页面)。 |
年轻人 | 每秒平均访问缓冲池 LRU 列表中导致页面年轻的旧页面。有关详细信息,请参阅此表后面的注释。 |
非年轻人 | 每秒平均访问缓冲池 LRU 列表中的旧页面,导致页面不年轻。有关详细信息,请参阅此表后面的注释。 |
阅读的页面 | 从缓冲池中读取的总页数。 |
创建的页面 | 在缓冲池中创建的页面总数。 |
写的页面 | 从缓冲池中写入的总页数。 |
读取/秒 | 每秒平均读取缓冲池页数。 |
创建/秒 | 每秒创建的缓冲池页的平均数。 |
写/秒 | 每秒平均写入缓冲池页数。 |
缓冲池命中率 | 从缓冲池读取页面与从磁盘存储读取页面的缓冲池页面命中率。 |
年轻化率 | 页面访问导致页面年轻化的平均命中率。有关详细信息,请参阅此表后面的注释。 |
不是(年轻化率) | 页面访问未导致页面年轻化的平均命中率。有关详细信息,请参阅此表后面的注释。 |
预读页面 | 预读操作的每秒平均值。 |
无法访问的页面被逐出 | 没有从缓冲池中访问而被逐出的页面的每秒平均值。 |
随机预读 | 随机预读操作的每秒平均值。 |
LRU 长度 | 缓冲池 LRU 列表的页面总大小。 |
unzip_LRU 长度 | 缓冲池 unzip_LRU 列表的长度(以页为单位)。 |
输入输出总和 | 访问的缓冲池 LRU 列表页总数。 |
输入/输出电流 | 当前时间间隔内访问的缓冲池 LRU 列表页总数。 |
I/O解压缩总和 | 解压缩的缓冲池 unzip_LRU 列表页总数。 |
I/O 解压缩 | 当前时间间隔内解压缩的缓冲池 unzip_LRU 列表页总数。 |
注意事项:
该
youngs/s
指标仅适用于旧页面。它基于页面访问次数。给定页面可以有多次访问,所有这些都被计算在内。如果youngs/s
在没有发生大型扫描时看到非常低的值,请考虑减少延迟时间或增加用于旧子列表的缓冲池的百分比。增加百分比会使旧的子列表变大,从而使该子列表中的页面移动到尾部的时间更长,从而增加了再次访问这些页面并使其成为年轻页面的可能性。请参阅 第 14.8.3.2 节,“使缓冲池具有抗扫描性”。该
non-youngs/s
指标仅适用于旧页面。它基于页面访问次数。给定页面可以有多次访问,所有这些都被计算在内。如果在执行大型表扫描时没有看到更高的non-youngs/s
值(以及更高的youngs/s
值),请增加延迟值。请参阅 第 14.8.3.2 节,“使缓冲池具有抗扫描性”。该
young-making
速率考虑了所有缓冲池页面访问,而不仅仅是旧子列表中页面的访问。young-making
rate 和not
rate 通常加起来不等于整体缓冲池命中率。旧子列表中的页面命中导致页面移动到新子列表,但新子列表中的页面命中导致页面仅在距离头部一定距离时移动到列表头部。not (young-making rate)
innodb_old_blocks_time
是由于未满足定义的延迟或由于新子列表中的页面命中未导致页面移动到头部而导致页面访问未导致页面年轻的平均命中率 。此速率考虑了所有缓冲池页面访问,而不仅仅是对旧子列表中页面的访问。
缓冲池服务器状态变量和该
INNODB_BUFFER_POOL_STATS
表提供了许多与
InnoDB
标准监视器输出中相同的缓冲池指标。有关详细信息,请参阅
示例 14.10,“查询 INNODB_BUFFER_POOL_STATS 表”。