#### 15.8.3.3 使缓冲池扫描抗性

[](<>)[](<>)[](<>)[](<>)[](<>)[](<>)[](<>)

而不是使用严格的[LRU](glossary.html#glos_lru)算法，`InnoDB`使用一种技术来最小化带入的数据量[缓冲池](glossary.html#glos_buffer_pool)并且再也没有访问过。目标是确保经常访问的（“热”）页面保留在缓冲池中，即使在[预读](glossary.html#glos_read_ahead)和[全表扫描](glossary.html#glos_full_table_scan)引入之后可能会或可能不会访问的新块。

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

对于内部工作原理的解释`InnoDB`缓冲池和有关 LRU 算法的细节，请参阅[第 15.5.1 节，“缓冲池”](innodb-buffer-pool.html).

可以控制LRU列表中的插入点，选择是否`InnoDB`对通过表或索引扫描带入缓冲池的块应用相同的优化。配置参数[`innodb_old_blocks_pct`](innodb-parameters.html#sysvar_innodb_old_blocks_pct)控制 LRU 列表中“旧”块的百分比。默认值为[`innodb_old_blocks_pct`](innodb-parameters.html#sysvar_innodb_old_blocks_pct)是`37`，对应于原来的固定比例3/8。取值范围为`5`（缓冲池中的新页面很快就会老化）到`95`（只有 5% 的缓冲池预留给热页，使得算法接近熟悉的 LRU 策略）。

防止缓冲池被预读搅动的优化可以避免由于表或索引扫描引起的类似问题。在这些扫描中，通常会快速连续访问数据页几次，并且永远不会再被触摸。配置参数[`innodb_old_blocks_time`](innodb-parameters.html#sysvar_innodb_old_blocks_time)指定第一次访问页面后的时间窗口（以毫秒为单位），在此期间可以访问它而不移动到 LRU 列表的前面（最近使用的一端）。默认值为[`innodb_old_blocks_time`](innodb-parameters.html#sysvar_innodb_old_blocks_time)是`1000`.增加此值会使越来越多的块可能更快地从缓冲池中老化。

两个都[`innodb_old_blocks_pct`](innodb-parameters.html#sysvar_innodb_old_blocks_pct)和[`innodb_old_blocks_time`](innodb-parameters.html#sysvar_innodb_old_blocks_time)可以在 MySQL 选项文件中指定 (`我的.cnf`要么`我的.ini`) 或在运行时使用[`设置全球`](set-variable.html)陈述。在运行时更改值需要足够的权限来设置全局系统变量。看[第 5.1.9.1 节，“系统变量权限”](system-variable-privileges.html).

为了帮助您衡量设置这些参数的效果，`显示引擎 INNODB 状态`命令报告缓冲池统计信息。有关详细信息，请参阅[使用 InnoDB 标准监视器监视缓冲池](innodb-buffer-pool.html#innodb-buffer-pool-monitoring).

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

在大多数活动是 OLTP 类型的混合工作负载中，定期批量报告查询会导致大扫描，设置值[`innodb_old_blocks_time`](innodb-parameters.html#sysvar_innodb_old_blocks_time)在批处理运行期间可以帮助将正常工作负载的工作集保留在缓冲池中。

当扫描无法完全放入缓冲池的大表时，设置[`innodb_old_blocks_pct`](innodb-parameters.html#sysvar_innodb_old_blocks_pct)将值设置为较小的值可防止仅读取一次的数据占用缓冲池的很大一部分。例如，设置`innodb_old_blocks_pct=5`将只读取一次的数据限制为缓冲池的 5%。

扫描适合内存的小表时，在缓冲池中移动页面的开销较小，因此您可以离开[`innodb_old_blocks_pct`](innodb-parameters.html#sysvar_innodb_old_blocks_pct)在其默认值，甚至更高，例如`innodb_old_blocks_pct=50`.

的效果[`innodb_old_blocks_time`](innodb-parameters.html#sysvar_innodb_old_blocks_time)参数比预测更难[`innodb_old_blocks_pct`](innodb-parameters.html#sysvar_innodb_old_blocks_pct)参数，相对较小，随工作量变化较大。为了达到最佳值，如果调整后的性能改进，请进行自己的基准测试[`innodb_old_blocks_pct`](innodb-parameters.html#sysvar_innodb_old_blocks_pct)还不够。
