conv=fdatasync仅在dd写入完成后调用一次fdatasync()系统调用,只同步文件数据(不含atime等元数据),不干预中间缓存过程,故非逐块落盘;真逐块落盘需oflag=dsync绕过页缓存并每块同步。

dd conv=fdatasync 并不能确保“每一块内容都真实落盘”,它只在整个写入操作结束时强制将已缓存的数据同步到磁盘,不干预中间过程。想让数据真正可靠落盘,关键不是加 fdatasync,而是理解它做什么、不做什么,再搭配正确参数。
conv=fdatasync 的真实作用
- 它等价于在
dd最后调用一次fdatasync()系统调用。 - 只刷写文件数据本身(不刷全量元数据,比如访问时间 atime)。
- 不影响写入过程中的缓存行为:数据仍先写入页缓存(page cache),最后才一次性落盘。
- 所以它测的是“带缓存写 + 末尾强刷”的性能,适合评估连续大块写的持久化延迟,但不是逐块落盘。
✅ 正确理解:
fdatasync是“收尾保障”,不是“实时锁盘”。
怎样才算“每一块都真实落盘”?
要逼近逐块物理写入(即每次写都等磁盘确认),需满足两个条件:
- 绕过页缓存:避免数据滞留在内存中
- 每次写都强制同步:不让系统攒批
对应参数组合是:
-
oflag=dsync(推荐)
或 oflag=sync
二者区别:
-
dsync:仅保证数据写入磁盘,不刷元数据(如 inode 修改时间),开销略小,更贴近数据库日志行为。 -
sync:数据 + 全量元数据都刷盘,更严格、更慢。
示例命令(1GB 小块逐写,真实模拟日志场景):
dd if=/dev/zero of=/mnt/disk/testfile bs=4k count=262144 oflag=dsync status=progress
-
bs=4k:模拟典型日志写大小 -
oflag=dsync:每写一个 4K 块,就等它真正落盘再写下一个 -
status=progress:实时看速率(通常只有几 MB/s,反映真实随机写能力)
⚠️ 注意:这种模式极慢,但结果反映的是最严苛的 I/O 路径,适用于验证 SSD/NVMe 的 fsync 延迟或数据库 WAL 日志盘可靠性。
常见误区与避坑建议
❌ 误以为
conv=fdatasync+bs=4k= 逐块落盘
→ 实际仍是先攒满缓存再刷,fdatasync只在最后触发一次。❌ 混用
oflag=direct和conv=fdatasync
→direct已绕过缓存,fdatasync失效(无缓存可刷),此时应改用oflag=dsync或sync。❌ 在文件系统上测试却忽略挂载选项
→ 确保挂载时未启用noatime,nobarrier等削弱持久性的选项;对 ext4/xfs,可加data=ordered或barrier=1提升一致性。❌ 测试目标是普通文件(如
/tmp/test)
→ 文件系统缓存和日志机制会干扰结果。如需最底层验证,应写裸设备(如/dev/sdb),并配合oflag=direct,dsync。
验证是否真落盘的小技巧
- 写完后立即断电(仅限离线测试环境!),再开机检查文件 md5 或用
hexdump看前几 KB 是否完整。 - 查看内核日志:
dmesg | grep -i "write cache",确认磁盘写缓存是否被禁用(hdparm -W0 /dev/sdX)。 - 监控脏页:
watch -n1 'grep -i dirty /proc/meminfo',若Dirty:值长期为 0,说明dsync确实在逐次清空。
不复杂但容易忽略。











