14.8.3.3 防止缓冲池扫描

InnoDB而不是使用严格的LRU算法,而是使用一种技术来最小化进入buffer pool且再也不会访问的数据量。目的是确保即使read-ahead全 table 扫描引入了以后可能会访问或可能不会访问的新块,缓冲池中仍会保留频繁访问的(“热”)页。

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

有关InnoDB缓冲池的内部工作原理以及有关 LRU 算法的详细信息,请参见第 14.5.1 节“缓冲池”

您可以控制 LRU 列 table 中的插入点,并选择InnoDB是否对 table 扫描或索引扫描带入缓冲池的块应用相同的优化。配置参数innodb_old_blocks_pct控制 LRU 列 table 中“旧”块的百分比。 innodb_old_blocks_pct的默认值为37,对应于原始固定比率 3/8.值范围是5(缓冲池中的新页面很快老化)到95(仅 5%的缓冲池保留给热页面使用,这使算法与熟悉的 LRU 策略非常接近)。

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

innodb_old_blocks_pctinnodb_old_blocks_time都可以在 MySQL 选项文件(my.cnfmy.ini)中指定,也可以在运行时使用SET GLOBAL语句进行更改。在运行时更改值需要足够的特权来设置全局系统变量。参见第 5.1.8.1 节“系统变量特权”

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

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

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

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

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

innodb_old_blocks_time参数的效果比innodb_old_blocks_pct参数的效果更难预测,相对较小,并且随工作负载而变化更大。要获得最佳值,如果调整innodb_old_blocks_pct所带来的性能改善不足,请执行自己的基准测试。

首页