rrqm/s 和 wrqm/s 是 iostat -x 中唯一直接反映 IO 合并行为的字段,表示每秒被调度器在入队前合并掉的读/写请求数;值为 0 不代表无合并,需结合 avgrq-sz、avgqu-sz、r_await/w_await 趋势及 blktrace(grep 'M')验证真实合并。

怎么用 iostat -x 看请求合并是否发生
rrqm/s 和 wrqm/s 是唯一直接体现块层请求合并行为的字段,它们不是“省掉了多少请求”,而是“被调度器在入队前合并掉的读/写请求数”。值为 0 不代表没合并——可能因为队列太浅、IO 地址太分散,或请求刚进队就立刻下发,根本没排队机会。
真正要确认合并是否生效,得结合其他字段交叉判断:
-
avgrq-sz:平均请求大小(扇区数)。HDD 上若长期 >64(即 >32KB),大概率有合并;NVMe 上该值普遍更高,但不能单靠它下结论 -
avgqu-sz:平均队列长度。相同吞吐下,avgqu-sz明显下降 +rrqm/s上升,是合并起效的典型信号 -
r_await/w_await:若等待时间显著缩短,且rrqm/s同步上升,说明合并减少了排队次数
为什么改了 /sys/block/sda/queue/nomerges 没变化
修改后 rrqm/s 无响应,常见原因不是配置没生效,而是 IO 路径绕过了你改的那个设备节点:
- 应用用了
O_DIRECT或posix_fadvise(POSIX_FADV_DONTNEED),跳过页缓存,削弱合并机会 - 实际 IO 走的是 LVM 或加密层(如
dm-0),你改的是sda,但调度器在dm-0层做合并,应检查并修改/sys/block/dm-0/queue/nomerges - 设备是 NVMe,多队列设计导致每个 CPU 队列独立,
nomerges只作用于单个 queue,全局rrqm/s看起来仍不为 0 - writeback 模式下大量 write 被延迟提交,
iostat统计的是最终下发到块层的 request,不是 syscall 原始调用
怎样验证合并真实发生了
最可靠的方式是用 blktrace 抓取底层块事件流,看有没有 M(merged)标记:
sudo blktrace -d /dev/sda -w 5 -o - | sudo blkparse | grep 'M'
只要输出里有带 M 的行,就证明前向或后向合并确实发生了。注意三点:
- 必须用
sudo,普通用户无权限 - 命令会短暂增加 I/O 开销,生产环境慎用
- 如果输出为空,再查
blktrace是否支持该设备(部分 NVMe 驱动不完全兼容)
iostat 输出里哪些字段容易误读
很多人把 %util 当成磁盘忙闲百分比,其实它是“队列非空时间占比”,高值只说明请求排队密集,不等于物理磁盘饱和;await 包含队列等待 + 服务时间,若 svctm 很低但 await 很高,问题在排队而非磁盘本身。
真正反映合并效果的字段只有 rrqm/s/wrqm/s,但它们数值小、波动大,单次采样意义有限。建议连续采样 10 秒以上(iostat -x 1 10),观察趋势而非瞬时值。
合并是个隐式优化,它不报错也不打日志,只能靠组合指标+底层 trace 交叉印证。别只盯着一个数字,尤其别拿 rrqm/s == 0 就断定“没合并”——那往往只是合并发生在更上游(比如文件系统层)或太快没留下痕迹。


















