先看现象。腾讯云 CVM 上 Ubuntu 22.04,ESSD 云盘做 MySQL 数据盘,scheduler 还是 mq-deadline,改成 none 之后压测 p99 从 2ms 涨到 9ms,iostat 的 aqu-sz 一直在 30 以上。
原因不止一个,得分开看。队列深度只有 32,none 不做合并排序,随机小 IO 直接把队列打满。另一种情况是云盘的 IOPS 有基线限制,换调度器动不了后端的排队。
不容易想到的是,MySQL 的 IO 线程数只有 4,并发太低,none 的顺序性优势用不上。
还有一种情况,文件系统挂载带了 sync,换调度器也躲不开同步写。
上来先确认当前调度器和队列深度
cat /sys/block/vdb/queue/scheduler /sys/block/vdb/queue/nr_requests
两种调度器下跑同一份压测
fio --name=randrw --rw=randrw --bs=4k --iodepth=32 --numjobs=4 --runtime=30 --filename=/dev/vdb --direct=1 --group_reporting
然后按队列深度切回 deadline
echo mq-deadline > /sys/block/vdb/queue/scheduler && cat /sys/block/vdb/queue/scheduler
末了确认挂载参数没有同步写
findmnt -no OPTIONS /data
我习惯把每一步的执行时间和结果记在一边,后面复盘省事。
恢复的判定其实很直接。同一份 fio 参数的 p99 回到 3ms 以内,aqu-sz 峰值降到 8 以下,MySQL 的 insert 延迟恢复正常。
补一句。单队列 NVMe 云盘用 none 合适,机械盘和深队列才需要 mq-deadline 做合并;调度器只是最后一层,IOPS 额度不够还是得换盘。这类问题最好一次改到位,反复小改反而容易把原因搅混。
