缓冲池是主存中的一个区域,InnoDB 在访问时缓存表和索引数据。缓冲池允许直接从内存访问频繁使用的数据,这加快了处理速度。在专用服务器上,高达80% 的物理内存通常分配给缓冲池。
为了提高大容量读取操作的效率,将缓冲池划分为可能包含多行的页。为了提高缓存管理的效率,缓冲池被实现为一个链接的页面列表; 使用最近使用次数最少(LRU)算法的一个变体,很少使用的数据被老化到缓存之外。
了解如何利用缓冲池将频繁访问的数据保存在内存中是 MySQL 调优的一个重要方面。
缓冲池 LRU 算法
使用 LRU 算法的变体将缓冲池作为列表进行管理。当需要空间向缓冲池添加新页面时,将删除最近使用次数最少的页面,并在列表中间添加一个新页面。这个中点插入策略将列表视为两个子列表:
头部是最近访问的新(“年轻”)页面的子列表
在尾部,是最近访问较少的旧页面的子列表
该算法将频繁使用的页保存在新的子列表(New Sublist)中。旧的子列表(Old Sublist)包含使用频率较低的页面; 这些页面可能会被驱逐。
默认情况下,算法运行如下:
缓冲池的3/8用于旧的子列表(Old Sublist)。
列表的中点是新子列表的尾部与旧子列表的头部相接的边界。
当 InnoDB 将页读入缓冲池时,它首先将页插入到中点(旧子列表的头部)。一个页面可以被读取,因为它是由用户发起的操作(如SQL查询)所必需的,或者是由InnoDB自动执行的预读操作的一部分。
访问旧子列表中的页面使其“年轻”,并将其移动到新子列表的头部。如果由于用户发起的操作要求读取该页,则会立即进行第一次访问,并使该页年轻化。如果由于预读操作而读取了该页,则第一次访问不会立即发生,并且在逐出该页之前可能根本不会发生。
随着数据库的运行,缓冲池中没有通过向列表尾部移动来访问“ age”的页面。新旧子列表中的页面随着其他页面的更新而老化。旧子列表中的页也会随着页插入中点而老化。最终,一个未使用的页面到达旧子列表的尾部并被驱逐。
默认情况下,查询读取的页面会立即移动到新的子列表中,这意味着它们在缓冲池中停留的时间更长。例如,对于 mysqldump 操作或没有 WHERE 子句的 SELECT 语句执行的表扫描可以将大量数据带入缓冲池,并驱逐等量的旧数据,即使新数据不再使用。类似地,由提前读取的后台线程加载并且只访问一次的页将移动到新列表的头部。这些情况可能会把经常使用的页面推到旧的子列表中,在那里它们会被驱逐出去。
InnoDB Standard Monitor的输出在BUFFER POOL AND MEMORY部分包含了几个关于BUFFER POOL LRU算法操作的字段。
缓冲池配置
您可以配置缓冲池的各个方面以提高性能。
理想情况下,可以将缓冲池的大小设置为尽可能大的值,为服务器上的其他进程留下足够的内存,以便在不进行过多分页的情况下运行。缓冲池越大,InnoDB 就越像一个内存数据库,从磁盘读取一次数据,然后在随后的读取过程中从内存中访问数据。
在具有足够内存的64位系统上,可以将缓冲池拆分为多个部分,以最小化并发操作之间对内存结构的争用。
您可以将频繁访问的数据保存在内存中,而不必考虑操作中突然出现的活动峰值,这些活动峰值会将大量不常访问的数据带入缓冲池。
您可以控制如何以及何时执行预读请求,以异步地将页预取到缓冲池中,以预期即将出现的需求。
您可以控制何时发生后台刷新,以及是否根据工作负载动态调整刷新速率。
您可以配置 InnoDB 如何保留当前缓冲池状态,以避免服务器重新启动后的冗长预热期。
使用 InnoDB 标准监视器监视缓冲池
InnoDB Standard Monitor 输出(可以使用 SHOW ENGINE INNODB STATUS 访问)提供了有关缓冲池操作的指标。缓冲池指标位于 InnoDB Standard Monitor 输出的 BUFFER POOL AND MEMORY 部分:
下表描述了 InnoDB 标准监视器报告的缓冲池指标。
InnoDB Standard Monitor 输出中提供的每秒平均值是基于自上次打印 InnoDB Standard Monitor 输出以来的运行时间。
InnoDB 缓冲池指标
注意:
young/s 指标只适用于旧页面。它基于页面访问次数。对于一个给定的页面,可以有多个访问,所有这些访问都将被计数。如果在没有进行大规模扫描时看到非常低的 young/s 值,请考虑减少延迟时间或增加用于旧子列表的缓冲池的百分比。增加百分比会使旧的子列表变大,这样子列表中的页面移动到尾部所需的时间就会更长,这就增加了再次访问这些页面并使其年轻化的可能性。
non-youngs/s 指标仅适用于旧页面。它基于页面访问次数。对于一个给定的页面,可以有多个访问,所有这些访问都将被计数。如果在执行大型表扫描时没有看到较高的 non-young/s 值(以及较高的 young/s 值) ,则增加延迟值。
young-making 速率解释了所有缓冲池页访问,而不仅仅是对旧子列表中的页的访问。young-making 速率和 not 速率通常加起来不等于整个缓冲池命中率。旧子列表中的页面命中会导致页面移动到新子列表,但是新子列表中的页面命中会导致页面移动到列表的头部,只有当页面与头部有一定距离时才会如此。
not (young-making rate)是由于innodb_old_blocks_time定义的延迟不满足,或者由于新子列表中的页面点击没有导致页面被移动到头部而导致页面不年轻的平均点击率。这个速率说明了所有缓冲池页面访问,而不仅仅是旧子列表中页面的访问。
缓冲池服务器状态变量和 INNODB _ BUFFER _ POOL _ STATS 表提供了许多与 InnoDB Standard Monitor 输出中相同的缓冲池指标。