从 InnoDB 了解到,plugin 1.0.4 开始,提供了一个新的脏数据刷新机制,被称为: innodb_adaptive_flushing 。由于之前在各种性能测试以及线上环境的性能监控中时常遇到当 InnoDB 在进行大批量 Dirty Page 的 Flush 过程中,会对系统的整体性能造成不小的影
从 InnoDB 了解到,plugin 1.0.4 开始,提供了一个新的脏数据刷新机制,被称为: innodb_adaptive_flushing 。由于之前在各种性能测试以及线上环境的性能监控中时常遇到当 InnoDB 在进行大批量 Dirty Page 的 Flush 过程中,会对系统的整体性能造成不小的影响,所以个人对这个新机制比较感兴趣,仔细分析了下这个机制到底改善了些什么内容。
一般来说,InnoDB 有两种情况会触发 Flush Dirty Page 的操作。如下:
当 InnoDB 的 redo log 进行切换重用其他某个日志的之前,被重用日志上的所有更改都必须全部记录进入数据文件,以确保主机在异常情况下 Crash 后不会造成数据丢失。这时候的 Flush 通常被称为 Flush_List Flush。
当我们请求某个 block 的时候,如果该 block 不在 buffer pool 中,我们就必须先将该 block 从磁盘文件中读入到 buffer pool 中。如果这时候我们的 buffer pool 中已经没有空余空间可以使用了,那 InnoDB 就会通过 LRU 机制,将某些 Dirty Page 写入数据文件以清理出需要的空闲空间。我们通常称这种 Flush 为 LRU_List Flush。
通过测试,很容易发现平时 LRU_List Flush 所带来的 Flush Dirty Page 的操作对 MySQL 整体性能的影响并不是特别大,很多时候带来性能冲击的主要是 Flush_List Flush 造成,主要是由于当我们进行日志切换的时候,已经积累与被重用的日志相关的较大量的 Dirty Page 需要被 Flush,所以短时间内会造成较大量的写磁盘 IO 发生,自然会影响系统整体性能。
为了解决短时间内出现大量写磁盘 IO,唯一的解决办法就是减少 Dirty Page 的量。所以 InnoDB 引入了 Adaptive Flush 的机制:通过内部的一些算法,以比较保守的方式来刷新 Dirty Page,以确保当我们需要进行日志切换的时候,只需要 Flush 很少量的 Dirty Page 就可以进行切换。
通过 InnoDB 的一些资料,Adaptive Flush 机制中,最关键的部分是如何得到后台 Flush 线程的 Flush 速度。毕竟 Flush 太快的话,可能会造成由于无法合理利用 IO 合并的机制,造成很多 block 在短时间内频繁的进出 Buffer Pool,带来相反的性能效果。所以刷新速度的算法就至关重要了,从 InnoDB 的一些资料了解到,基本算法大体如下描述:
首先通过日志剩余量 除以 日志产生速度 得出 切换前可以使用的时间:
time_remainning = log_capacity / redo_gen_rate
那么我们必须在 time_remainning 时间范围内完成所有 Dirty Page 的刷新,所以可以计算出刷新速度:
flush_rate = dirty_page_numbers / time_remaining = dairty_page_numbers * redo_gen_rate / log_capacity
最后,我们将刷新速度减掉 LRU_List Flush 的刷新速度,就可以得出 Adaptive Flush 的速度了:
adaptive_flush_rate = flush_rate – lru_flush_rate = dairty_page_numbers * redo_gen_rate / log_capacity – lru_flush_rate
InnoDB 专门为这个特性设置了一个参数 innodb_adaptive_flushing,让 DBA 可以控制是否开始 Adaptive Flush 这项特性,在默认情况下该特性是开启的,我们可以通过这个参数来关闭。
从这个特性我们看到了 InnoDB 已经正在不断的向 Oracle 的很多特性靠近了,希望以后能带来越来越多 Oracle 中才有的特性,尤其是方便 DBA 运维的特性,这一块 MySQL 还存在较大的欠缺。
原文地址:InnoDB Adaptive Flush, 感谢原作者分享。