记录一下那天晚上的排查过程。跑 MySQL 的 ESSD 云盘机器在业务高峰 iostat 里 aqu-sz 到三十,r_await 从 0.4ms 涨到 8ms,QPS 掉一半,磁盘 util 只有六成。
刚开始盯着「后台刷脏与业务读混在一起抢占队列」,折腾了半个多小时,排掉了。
排查方向其实有限,先把可能性排一排。并发请求数远超云盘能承受的队列深度。还有一种是单条 SQL 一次读太多页,把小 IO 攒成大 IO。
少数情况下是文件系统层没有合并相邻的请求。
上来先观察队列深度与延迟的对应关系
iostat -xmd 2 10
再往下确认是哪类 IO 在排队
pidstat -d 2 10
降低刷脏频率削平写毛刺
sysctl -w vm.dirty_ratio=10 && sysctl -w vm.dirty_background_ratio=5
剩下的就是核对 IO 能力与读取行数配置
mysql -e "show variables like 'innodb_io_capacity' and 'innodb_io_capacity_max';"
改完先别撤,确认这几项。调整后 aqu-sz 稳定在个位数,r_await 回到 1ms 以内,业务 QPS 恢复到高峰前的水平。
容易忽略的是,util 到顶不代表设备到极限,队列深度更能反映排队情况;云盘的队列深度按盘共享,同账号别的盘打满也会影响。这类问题最好一次改到位,反复小改反而容易把原因搅混。
