innodb_idle_flush_pct 参数是 MySQL 8.0.18 版本引入的新参数,用于InnoDB空闲状态下,限制刷脏页的速度。
innodb_idle_flush_pct:
- 作用范围:Global
- 动态修改:Yes
- 默认值:100
- 最小值:0
- 最大值:100
innodb_idle_flush_pct 的值是一个百分比,该百分比乘以基数,也就是参数 innodb_io_capacity 值,获得的结果即为InnoDB空闲状态下刷脏页的速度。
举个例子:
设置innodb_io_capacity=1000,设置innodb_idle_flush_pct=50,那么在空闲状态下,InnoDB刷脏页的速度为 500。
innodb_idle_flush_pct 参数源码分析:
源码版本:8.0.20
innodb_idle_flush_pct默认值为100,如下:
// 源码文件 srv0srv.cc
const ulong srv_idle_flush_pct_default = 100;
ulong srv_idle_flush_pct = srv_idle_flush_pct_default;
调用函数buf_flush_lists(),传入srv_idle_flush_pct参数,来控制InnoDB空闲状态下刷脏页的速度,如下:
// 源码文件 buf0flu.cc
else if (ret_sleep == OS_SYNC_TIME_EXCEEDED && srv_idle_flush_pct) {
/* no activity, slept enough */
buf_flush_lists(PCT_IO(srv_idle_flush_pct), LSN_MAX, &n_flushed);
}
PCT_IO 宏定义:
// 源码文件 srv0srv.h
#define PCT_IO(p) ((ulong)(srv_io_capacity * ((double)(p) / 100.0)))
buf_flush_lists()函数,调用buf_flush_do_batch()函数,传入参数min_n,控制刷脏页速度,主要逻辑如下:
// 源码文件 buf0flu.cc
bool buf_flush_lists(ulint min_n, lsn_t lsn_limit, ulint *n_processed) {
if (min_n != ULINT_MAX) {
/* Ensure that flushing is spread evenly amongst the
buffer pool instances. When min_n is ULINT_MAX
we need to flush everything up to the lsn limit
so no limit here. */
min_n = (min_n + srv_buf_pool_instances - 1) /
srv_buf_pool_instances;
}
/* Flush to lsn_limit in all buffer pool instances */
for (ulint i = 0; i < srv_buf_pool_instances; i++) {
buf_pool_t *buf_pool;
ulint page_count = 0;
buf_pool = buf_pool_from_array(i);
if (!buf_flush_do_batch(buf_pool, BUF_FLUSH_LIST, min_n, lsn_limit,
&page_count)) {
/* We have two choices here. If lsn_limit was
specified then skipping an instance of buffer
pool means we cannot guarantee that all pages
up to lsn_limit has been flushed. We can
return right now with failure or we can try
to flush remaining buffer pools up to the
lsn_limit. We attempt to flush other buffer
pools based on the assumption that it will
help in the retry which will follow the
failure. */
success = false;
continue;
}
n_flushed += page_count;
}