脏页的定义
- 内存中的数据页跟磁盘中的数据页不一致的时候,这些数据页就是脏页
需要刷新脏页的场景
- InnoDB的redo log写满了
- 系统内存不足
- 系统空闲时(不影响性能)
- 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很高