MySQL-InnoDB 刷脏页的控制策略
以下内容来自mysql45讲第12讲-为什么我的mysql会抖一下
正确地告诉 InnoDB 所在主机的 IO 能力,这样 InnoDB 才能知道需要全力刷脏页的时候,可以刷多快。
innodb_io_capacity
这个参数它会告诉 InnoDB 你的磁盘能力。这个值建议设置成磁盘的 IOPS。
磁盘的 IOPS 可以通过 fio 这个工具来测试
fio -filename=/tmp/iops.txt -direct=1 -iodepth 1 -thread -rw=randrw -ioengine=psync -bs=16k -size=500M -numjobs=10 -runtime=10 -group_reporting -name=mytest
#参数说明:
-filename=/tmp/iops.txt --测试文件或者磁盘名称,文件不存在会自动创建。
-direct=1 --测试过程绕过机器自带的缓冲区,使测试结果更真实。
-iodepth --IO队列深度,主要根据设备的并行度来调整。
-thread
-rw=randrw --随机读写,可选randwrite|randread|read|write|randrw
-ioengine=psync --IO引擎使用psync,也可以选择libaio
-bs=16k --单次IO块大小为16KB
-size=500M --测试文件大小为 5GB。
-numjobs=10 --测试线程为10个
-runtime=10 --测试时间为10秒,也可以持续时间长点比如1000秒
-group_reporting --设置显示结果,指定group_porting将汇总每个进程的信息。
其实,因为没能正确地设置 innodb_io_capacity
参数,而导致的性能问题也比比皆是。之前,就曾有其他公司的开发负责人找我看一个库的性能问题,说 MySQL 的写入速度很慢,TPS 很低,但是数据库主机的 IO 压力并不大。经过一番排查,发现罪魁祸首就是这个参数的设置出了问题。
他的主机磁盘用的是 SSD,但是 innodb_io_capacity
的值设置的是 300。于是,InnoDB 认为这个系统的能力就这么差,所以刷脏页刷得特别慢,甚至比脏页生成的速度还慢,这样就造成了脏页累积,影响了查询和更新性能
刷脏时机:
- InnoDB 的 redo log 写满了。这时候系统会停止所有更新操作,把 checkpoint 往前推进,redo log 留出空间可以继续写。
- 系统内存不足。当需要新的内存页,而内存不够用的时候,就要淘汰一些数据页,空出内存给别的数据页使用。如果淘汰的是“脏页”,就要先将脏页写到磁盘。
- MySQL 认为系统“空闲”的时候。
- MySQL 正常关闭的情况。这时候,MySQL 会把内存的脏页都 flush 到磁盘上,这样下次 MySQL 启动的时候,就可以直接从磁盘上读数据,启动速度会很快。
控制刷脏策略考虑因素:
-
脏页比例:
参数innodb_max_dirty_pages_pct
是控制脏页比例上限,默认值是75%, 表示当Buffer Pool中的脏数据页达到整体缓存的75%时,触发刷新的动作。
脏页比例是通过Innodb_buffer_pool_pages_dirty/Innodb_buffer_pool_pages_total
得到的 -
redo log 写盘速度:
一个内存配置为 128GB、innodb_io_capacity 设置为 20000 的大规格实例,正常会建议你将 redo log 设置成 4 个 1GB 的文件。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?