Mysql刷脏页的二三事

我们知道MySQL 的innodb引擎使用redo log 实现crash safe, 并且更新数据时,先更新内存,然后写完redo log,然后后台线程将redo log 异步刷入磁盘。

内存与磁盘的数据页不一致,这样的数据页叫做脏页,mysql偶尔查询慢,可能就是在刷脏页到磁盘,刷脏页有几种情况:

  1. redo log 写满了
  2. mysql内存满了,发生内存置换。当要置换出去的是脏页时,就会刷脏页
  3. mysql系统空闲时
  4. mysql停止服务的时候

1和2才是我们关注的对象,redo log写满了,必须停下来刷脏页,此时完全完全不能写入。innodb 使用buffer pool管理内存,如果要查询的数据不在内存中,需要从磁盘读入内存,可能会淘汰掉一批很久没使用的数据页。如果淘汰的数据页比较多,会花时间去刷脏页,造成的影响就是查询变慢了。

刷脏页的控制策略

innodb_io_capacity

这个参数设置为磁盘的IOPS,机械磁盘一般为300,SSD的话往上配置。

innodb_max_dirty_pages_pct

参数 innodb_max_dirty_pages_pct 是脏页比例上限,默认值是 75%。当前的刷脏页比例,由附件"InnoDB 刷脏页速度策略"。假设当前脏页比例为M,有如下计算规则:

F1(M)
{
     if M >= innodb_max_dirty then 
         return 100;
     return 100*M/innodb_max_dirty_pages_pct;
}

另外还有个计算规则,记为F(N), N代表了redo log当前的余裕部分大小(当前写入日志位置序号和checkpoint位置序号的差值)。

刷脏页速度大概可以这样给出公式

innodb_io_capacity * max(F(M), F(N)) x !00%

合理设置 innodb_io_capacity 的值,并且平时要多关注脏页比例,不要让它经常接近 75。

监控刷脏页

use information_schema;
set @@global.show_compatibility_56=ON;
select VARIABLE_VALUE into @a from global_status where VARIABLE_NAME = 'Innodb_buffer_pool_pages_dirty';
select VARIABLE_VALUE into @b from global_status where VARIABLE_NAME = 'Innodb_buffer_pool_pages_total';
select @a/@b;

innodb_flush_neighbors

innodb_flush_neighbors 设置为1 时,表示刷脏页的时候会连带将附近的脏页一起刷盘,设置这个参数对机械键盘有用,如果时SSD iops比较高,可以关掉,减少一些sql语句响应时间。

原文地址:https://www.cnblogs.com/linyihai/p/15729639.html