MySQL学习笔记 - 6 - 脏页刷新策略

2,879 阅读2分钟

脏页的定义

  • 内存中的数据页跟磁盘中的数据页不一致的时候,这些数据页就是脏页

需要刷新脏页的场景

  1. InnoDB的redo log写满了
  2. 系统内存不足
  3. 系统空闲时(不影响性能)
  4. MySQL正常关闭过程(不影响性能)

刷新脏页的场景分析

场景1 - InnoDB的redo log写满了

这种情况要尽量避免,出现这种情况的时候,整个系统就不能再接受更新了,所有更新都将被阻塞

场景2 - 系统内存不足

内存不足是指InnoDB中的buffer pool的剩余内存不足

buffer pool中的数据页有三种状态:

  • 还未使用
  • 使用后,仍然是干净页
  • 使用后,变成脏页

数据页从磁盘读入内存时,需要向buffer_pool申请一个数据页,buffer_pool会根据LRU算法淘汰一个数据页,如果淘汰的数据页是脏页,那么会先将脏页数据刷新到磁盘中,然后才复用数据页;如果一个查询要淘汰掉的脏页太多了,会导致查询的响应时间变长

  • InnoDB从磁盘中加载数据的时候,是以数据页作为单位的,默认数据页大小为16K,通过参数innodb_page_size可以设置数据页的大小(从MySQL5.6开始可以通过这个参数调整,但是5.6以前,需要修改源码中的UNIV_PAGE_SIZE相关值)
  • buffer_pool中的LRU算法是改进后的URL算法,目的是为了InnoDB加载冷数据的同时,可以保持buffer_pool的内存命中率
  • buffer_pool是InnnoDB的缓冲池,里面包含了各种buffer,例如change_buffer、join_buffer等等

设置脏页刷新策略

  • 想要InnoDB以合理的速度去刷新脏页,首先需要先告诉InnoDB,所在主机的磁盘IO能力,然后通过设置innodb_io_capacity参数,指定InnoDB刷新脏页的速度上限
  • InnDB根据两个因素来判断刷新脏页的速度
    • buffer_pool中的脏页比例 innodb_buffer_pool_pages_dirty/innodb_buffer_pool_pages_total
    • redo log中的剩余空间

邻居连坐机制

刷脏页的额时候,如果发现脏页旁边的数据页(邻居)也是脏页,就会将这个邻居也一并刷掉,以此类推

  • 通过参数innodb_flush_neighbors控制该机制

    • innodb_flush_neighbors = 1表示启用
    • innodb_flush_neighbors = 0表示禁用
  • 连坐机制对于机械硬盘是很有意义的,机械硬盘IOPS比较低,通过连坐机制可以减少大量随机IO

  • 对于SSD设备,建议设置innodb_flush_neighbors = 0,因为SSD的IOPS很高