Documentation Home

14.8.3.3 使缓冲池扫描抵抗

不是使用严格的LRU 算法,而是InnoDB使用一种技术来最小化带入 缓冲池并且再也不会访问的数据量。目标是确保频繁访问的()页面保留在缓冲池中,即使预读全表扫描 引入了之后可能会或可能不会访问的新块。

新读取的块被插入到 LRU 列表的中间。所有新读取的页面都插入到默认情况下3/8位于 LRU 列表尾部的位置。当页面第一次在缓冲池中被访问时,它们被移动到列表的前面(最近使用的一端)。因此,从未访问过的页面永远不会进入 LRU 列表的前面部分,并且比使用严格的 LRU 方法更快地过时” 。这种安排将 LRU 列表分为两个部分,其中插入点下游的页面被认为是旧的并且是 LRU 驱逐的理想受害者。

有关 InnoDB缓冲池的内部工作原理和 LRU 算法的细节的解释,请参阅第 14.5.1 节,“缓冲池”

您可以控制 LRU 列表中的插入点,并选择是否InnoDB对通过表扫描或索引扫描带入缓冲池的块应用相同的优化。配置参数 控制LRU 列表中innodb_old_blocks_pct块的百分比。默认值为 , 对应原来的固定比例3/8。取值范围为(缓冲池中的新页面老化很快)到 (缓冲池中只有5%留给热点页面,使得算法接近大家熟悉的LRU策略)。 innodb_old_blocks_pct37595

防止缓冲池被预读搅动的优化可以避免由于表或索引扫描而导致的类似问题。在这些扫描中,数据页通常会被快速连续访问几次,并且再也不会被访问。配置参数 innodb_old_blocks_time 指定第一次访问页面后的时间窗口(以毫秒为单位),在此期间可以访问该页面而不会移动到 LRU 列表的前面(最近使用的末尾)。innodb_old_blocks_time的默认 值为 1000。增加这个值会使越来越多的块可能从缓冲池中更快地老化。

innodb_old_blocks_pct和 都innodb_old_blocks_time可以在 MySQL 选项文件 (my.cnf或 ) 中指定,或者在运行时用语句my.ini更改 。SET GLOBAL在运行时更改值需要足够的权限来设置全局系统变量。请参阅第 5.1.8.1 节,“系统变量权限”

为了帮助您衡量设置这些参数的效果,该 SHOW ENGINE INNODB STATUS命令会报告缓冲池统计信息。有关详细信息,请参阅 使用 InnoDB 标准监视器监视缓冲池

由于这些参数的影响可能会根据您的硬件配置、数据和工作负载的详细信息而有很大差异,因此在任何性能关键或生产环境中更改这些设置之前,请始终进行基准测试以验证有效性。

在大多数活动是 OLTP 类型的混合工作负载中,定期批处理报告查询会导致大量扫描, innodb_old_blocks_time在批处理运行期间设置值有助于将正常工作负载的工作集保留在缓冲池中。

当扫描不能完全容纳在缓冲池中的大表时,设置 innodb_old_blocks_pct为较小的值可以防止仅读取一次的数据占用缓冲池的很大一部分。例如,设置 innodb_old_blocks_pct=5将只读取一次的数据限制为缓冲池的 5%。

当扫描适合内存的小表时,在缓冲池中移动页面的开销较小,因此您可以保留 innodb_old_blocks_pct其默认值,甚至更高,例如 innodb_old_blocks_pct=50.

参数的影响 innodb_old_blocks_time 比参数更难预测 innodb_old_blocks_pct ,相对较小,并且随工作负载的变化更大。为获得最佳值,如果调整带来的性能改进 innodb_old_blocks_pct不充分,请执行您自己的基准测试。