MySQL参数解析innodb_flush_neighbors

innodb_flush_neighbors 参数是InnoDB用来控制buffer pool刷脏页时是否把脏页邻近的其他脏页一起刷到磁盘,在传统的机械硬盘时代,打开这个参数能够减少磁盘寻道的开销,显著提升性能。

  • 取值范围:0,1,2
  • 默认值:5.7版本为1, 8.0版本为0

含义:

  • 设置为0时,表示刷脏页时不刷其附近的脏页。
  • 设置为1时,表示刷脏页时连带其附近毗连的脏页一起刷掉。
  • 设置为2时,表示刷脏页时连带其附近区域的脏页一起刷掉。1与2的区别是2刷的区域更大一些。

如果MySQL服务器磁盘是传统的HDD存储设备,打开该参数,能够减少I/O磁盘寻道的开销,提高性能,而对于SSD设备,寻道时间的性能影响很小,关闭该参数,反而能够分散写操作,提高数据库性能。由于SSD设备的普及,MySQL 8.0 将该参数的默认值由1调整为0。

innodb_flush_neighbors参数源码分析:

源码版本:5.7.19

在源码中,innodb_flush_neighbors 参数对应的变量为srv_flush_neighbors,这是一个全局变量,默认值为1,如下:

ulong srv_flush_neighbors = 1;

整个代码中,用到变量 srv_flush_neighbors 的地方只有一个,那就是函数 buf_flush_try_neighbors(),该函数位于源码文件:storage/innobase/buf/buf0flu.cc

buf_flush_try_neighbors() 函数主要逻辑,如下:

static ulint buf_flush_try_neighbors(
      const page_id_t&  page_id,
      buf_flush_t       flush_type,
      ulint             n_flushed,
      ulint             n_to_flush)
{

    if (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN
              || srv_flush_neighbors == 0) {
    
            // [low, high] 区间不包含邻近的页面
            low = page_id.page_no();
            high = page_id.page_no() + 1;

    }else{
            // [low, high] 区间包含邻近的页面
            low = (page_id.page_no() / buf_flush_area) * buf_flush_area;
            high = (page_id.page_no() / buf_flush_area + 1) * buf_flush_area;

            if (srv_flush_neighbors == 1) {
                ...
                // 根据 [low, high] 区间内的页是否可以刷盘,来进一步缩小 [low, high] 区间
            }
    }
    
    ...
    // 根据 [low, high] 区间进行脏页刷盘
}

buf_flush_try_neighbors() 函数根据 [low, high] 区间来刷脏页。

  • 当 srv_flush_neighbors 为 0时, [low, high] 只包含一个页面。
  • 当 srv_flush_neighbors 为 1时, [low, high] 包含邻近的页面,页面数小于等于变量值buf_flush_area。
  • 当 srv_flush_neighbors 为 2时, [low, high] 包含邻近的页面,页面数等于变量值buf_flush_area。

发表评论