配置MySQL Buffer Pool ,让缓冲池抵抗扫描
前言
缓存池污染也就是使用一些全表查询,将一些实际上不常用页面加入到了缓存池中,这样会造成热点数据淘汰。
所有新读取的页面,默认情况下都插入到位于 LRU 列表尾部3/8的位置。当页面第一次在缓冲池中被访问时,它们被移动到列表的前面(最近使用的一端)。
因此,从未访问过的页面永远不会进入 LRU 列表的前面部分,并且比使用严格的 LRU 方法更快地“过时” 。这种安排将 LRU 列表分为两个部分,其中插入点下游的页面被认为是“旧的”并且是被 LRU 最先淘汰的。
解决方法
1. 设置LRU列表的插入点 innodb_old_blocks_pct
控制 LRU 列表中的插入点,并选择是否InnoDB对通过表扫描或索引扫描带入缓冲池的块应用相同的优化。
配置参数 控制LRU 列表中“旧”innodb_old_blocks_pct块的百分比。默认值为 37, 对应原来的固定比例3/8。取值范围为5(缓冲池中的新页面老化很快)到 95(缓冲池中只有5%留给热点页面,使得算法接近大家熟悉的LRU策略)。
2. 设置第一次访问页面后的时间窗口 innodb_old_blocks_time
MySQL缓冲池加入了一个“老生代停留时间窗口”的机制:
- 假设T=老生代停留时间窗口;
- 插入老生代头部的页,即使立刻被访问,并不会立刻放入新生代头部;
- 只有满足“被访问”并且“在老生代停留时间”大于T,才会被放入新生代头部;
加入“老生代停留时间窗口”策略后,短时间内被大量加载的页,并不会立刻插入新生代头部,而是优先淘汰那些,短期内仅仅访问了一次的页。
在这些扫描中,数据页通常会被快速连续访问几次,并且再也不会被访问。配置参数 innodb_old_blocks_time 指定第一次访问页面后的时间窗口(以毫秒为单位),在此期间可以访问该页面而不会移动到 LRU 列表的前面(最近使用的末尾)。innodb_old_blocks_time的默认 值为 1000。增加这个值会使越来越多的块可能从缓冲池中更快地老化。
如何设置innodb_old_blocks_pct 和 innodb_old_blocks_time的参数?
innodb_old_blocks_pct和innodb_old_blocks_time都可以在 MySQL 选项文件 (my.cnf或 ) 中指定,或者在运行时用语句my.ini更改 。SET GLOBAL在运行时更改值需要足够的权限来设置全局系统变量。请参阅第 5.1.8.1 节,“系统变量权限”。
系统变量可以具有影响整个服务器操作的全局值、仅影响当前会话的会话值或两者。要修改系统变量运行时值,请使用该 SET 语句。请参阅第 13.7.4.1 节,“变量赋值的 SET 语法”。本节介绍在运行时为系统变量赋值所需的权限。
设置全局系统变量运行时值需要 SUPER权限。
要设置会话系统变量运行时值,请使用 SET SESSION语句。与设置全局运行时值相比,设置会话运行时值通常不需要特殊权限,任何用户都可以影响当前会话。对于某些系统变量,设置会话值可能会在当前会话之外产生影响,因此是一个受限操作,只能由具有 SUPER权限的用户完成。如果会话系统变量以这种方式受到限制,则变量描述会指示该限制。示例包括 binlog_format和 sql_log_bin. 设置这些变量的会话值会影响当前会话的二进制日志记录,但也可能对服务器复制和备份的完整性产生更广泛的影响。
如何衡量设置这些参数的效果?
使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带来的性能改进不充分,可以进行基准测试。