Making the Buffer Pool Scan Resistant
新读取的数据页被插入到buffer pool的LRU列表的中间位置,默认位置是从尾部开始算起的3/8的位置。当被放入buffer pool的页被第一次访问时就开始往列表的前方移动,而这样列表的后部就是不经常访问的页甚至是从不访问的页。
通过参数innodb_old_blocks_pct可以控制列表中”old” 数据页所占的百分比,默认是37%,等同于3/8,取值范围是5~95。
Innodb_old_blocks_time参数默认是1000毫秒,指定了页面读取到buffer pool后但没有移动到经常被访问列表位置的时间窗口。
InnoDB buffer pool预存取(read-ahead)
Read ahead是异步地预先获取多个数据页到buffer pool的IO操作,这些数据页都是假定会随后被用到的。 InnoDB通过两种read-ahead算法提高IO性能:
线性read ahead:预测哪些页会被顺��访问。通过innodb_read_ahead_threshold参数调整顺序数据页的数量。当从一个区中顺序读取的页数量大于等于
innodb_read_ahead_threshold时, innodb会触发异步read ahead操作将真个区都读到buffer pool中。该参数的默认值是56,取值范围是0~64。
随机read ahead:通过已经在buffer pool中的数据页来预测哪些页会被随后访问到。如果13个连续的处于相同区的页存在于buffer pool中,则InnoDB会把同一个区的其它页都读取进来。通过设置innodb_random_read_ahead=ON来开启此方式。
通过执行show engine innodb status命令显示的三个参数判断read-ahead算法的有效性:
Innodb_buffer_pool_read_ahead
Innodb_buffer_pool_read_ahead_evicted
Innodb_buffer_pool_read_ahead_rnd
Innodb会在后台将buffer pool中的脏页(已经修改但没有写到数据文件)flush掉。当buffer pool中的脏页所占百分比达到innodb_max_dirty_pages_pct_lvm会触发flush,当所占比例达到innodb_max_dirty_pages_pct时,则innodb会“强烈” 的flush。
针对数据修改操作频繁的系统, flush可能会严重滞后导致有大量的buffer pool内存占用,有一些参数专门针对修改繁忙的系统可以调整:
Innodb_adaptive_flushing_lwm:为防止redo log被填满,此参数设置一个阈值,如果redo log的容量超过此阈值,则执行adaptive flush操作。
Innodb_max_drity_pages_pct_lwm
Innodb_io_capacity_max
Innodb_flushing_avg_loops
InnoDB可以通过配置innodb_buffer_pool_dump_at_shutdown参数来确保在mysql正常重启时部分经常使用的数据页能直接加载到buffer pool中,通过批量加载的方式, 以节省重启mysql导致的warmup时间(原先在buffer pool中的数据页要从磁盘再次加载到内存中)。
Buffer pool的状态可以在任意时刻被保存,而重置状态也可以恢复任意保存的副本。
在数据库运行期间动态配置buffer pool数据页保留占比的方式是:
SET GLOBAL innodb_buffer_pool_dump_pct=40;
而在配置文件中的配置方法为:
[mysqld]
innodb_buffer_pool_dump_pct=40
配置当服务器关闭时保存buffer pool的当前状态的方法是:
SET GLOBAL innodb_buffer_pool_dump_at_shutdown=ON;
mysqld --innodb_buffer_pool_load_at_startup=ON;
默认情况下innodb_buffer_pool_dump_at_shutdown和innodb_buffer_pool_load_at_startup两个配置
是开启状态
在关闭MySQL时,会把内存中的热数据保存在磁盘里ib_buffer_pool文件中,位于数据目录下。
数据库运行期间保存和重新加载buffer pool的方法是:
SET GLOBAL innodb_buffer_pool_dump_now=ON;
SET GLOBAL innodb_buffer_pool_load_now=ON;
查看buffer pool保存和重新加载的进度的方法是:
mysql> SHOW STATUS LIKE 'Innodb_buffer_pool_dump_status';
+--------------------------------+--------------------------------------------------+
| Variable_name | Value |
+--------------------------------+--------------------------------------------------+
| Innodb_buffer_pool_dump_status | Buffer pool(s) dump completed at 170519 0:16:28 |
+--------------------------------+--------------------------------------------------+
1 row in set (0.00 sec)
mysql> SHOW STATUS LIKE 'Innodb_buffer_pool_load_status';
+--------------------------------+--------------------------------------------------+
| Variable_name | Value |
+--------------------------------+--------------------------------------------------+
| Innodb_buffer_pool_load_status | Buffer pool(s) load completed at 170519 0:14:05 |
+--------------------------------+--------------------------------------------------+
1 row in set (0.00 sec)
通过show engine innodb status\G;命令可以查看buffer pool的运行情况