不加oflag=direct的dd写测试测的是内存和文件系统缓存吞吐,而非磁盘真实写速;因内核仅将数据写入page cache即返回,数据尚未落盘,故2gb/s可能是缓存速度,硬盘实际仅约300mb/s。

不加 oflag=direct 的 dd 写测试,测的不是磁盘真实写速,而是内存和文件系统缓存的吞吐——你看到的 2GB/s 很可能只是 page cache 在跑,硬盘实际才 300MB/s。
为什么 dd if=/dev/zero of=testfile 默认结果虚高
内核在收到 write() 调用后,只要把数据塞进页缓存(page cache)就返回“成功”,dd 立刻结束计时。此时数据还卡在内存里,根本没发给磁盘驱动。尤其当 /mnt/data 是 ext4/xfs 文件系统时,日志、分配延迟、条带对齐等都会进一步掩盖真实落盘行为。
-
oflag=direct是绕过 page cache 的硬性开关,缺它等于白测 - 若目标路径是
/tmp(常为 tmpfs 内存文件系统),测出来的是 RAM 速度,和磁盘无关 -
conv=notrunc或seek=会引入寻址开销,不再是纯顺序写,速率失真
怎么写出一条靠谱的写入测试命令
目标是让数据真正落盘、可复现、不被干扰。关键参数必须明确指定:
-
of必须指向目标磁盘挂载点下的文件,例如/mnt/data/testfile(不能是/tmp或未挂载设备) -
bs=1M是 SSD 和 HDD 都较友好的起点;bs=4k适合模拟数据库小 IO,但会放大调度开销 -
count=2048→ 写 2GB,足够摊平预热抖动,又不至于跑太久 -
oflag=direct强制 O_DIRECT,跳过页缓存 - 别加
conv=fdatasync或oflag=sync—— 它们会强制刷写磁盘 DRAM 缓存(如 SATA SSD 或 RAID 卡的 write-back cache),导致速率骤降,那是“最严苛的真实落盘速度”,不是常规业务场景
最终命令示例:time dd if=/dev/zero of=/mnt/data/testfile bs=1M count=2048 oflag=direct
读取测试前必须清缓存,否则结果无效
刚写完就立刻 dd if=testfile of=/dev/null iflag=direct,很可能读到的是还在 DRAM 里的副本,尤其 NVMe 或带缓存的 SSD 上,结果比真实物理读快 2–5 倍。
- 读之前务必执行:
sudo sh -c "echo 3 > /proc/sys/vm/drop_caches"(需 root) -
iflag=direct同样重要,否则仍走 page cache - 如果提示
Invalid argument,说明文件系统不支持 direct I/O(如某些 FUSE 实现),此时去掉该 flag,但要清楚结果含缓存影响 - 对比参考:用
hdparm -t /dev/sdb测裸设备读速,若dd结果远高于它,基本确认缓存没清干净或元数据干扰严重
结果波动大?不是磁盘坏了,是变量没控住
同一块盘三次测试得 1.1GB/s、0.4GB/s、1.3GB/s,大概率是后台干扰或缓存残留,不是硬件问题。
- 单次测试偶然性极强,至少跑 3 次,取中间值(不是平均值)
- 测试期间关掉日志轮转、监控采集、备份任务等所有后台 IO
- SSD 或 RAID 卡有写缓存时,加
conv=fdatasync可强制刷盘,但速率会明显下降——这才是真实落盘能力,但代价是失去“典型应用层吞吐”参考价值 -
status=progress显示的实时速率不可信,只看最后输出的X bytes copied, Y s, Z MB/s行
真正容易被忽略的是:dd 只反映单流、大块、顺序写能力,对数据库、虚拟机这类小 IO 随机负载毫无参考价值——那得用 fio。











