最可靠方法是用 smartctl -g wcache /dev/sda 查看,返回“Write cache is: enabled”即启用;hdparm -I 仅适用于 SATA/ATA,NVMe 需用 nvme get-feature -f 0x06,而 sg_modes -p 8,0 适用于 SCSI/SAS 设备。

怎么确认磁盘是否启用了写缓存(Write Cache)
Linux 下不能靠 lsblk 或 hdparm -I 一眼断定写缓存开关状态——不同接口(SATA/SAS/NVMe)和厂商实现差异大,必须用对应工具查真实寄存器位。最可靠的是 smartctl -g wcache,它直接读取 ATA/SAT/SCSI 的 IDENTIFY DEVICE 数据或 MODE SENSE 页面。
执行前先确认设备路径是否为物理磁盘(不是 LVM 逻辑卷或 RAID 虚拟设备):ls -l /sys/block/sdX/device 应指向 hostX/targetX:X:X/X:X:X:X;若看到 dm-* 或 md*,说明已抽象过层,smartctl 可能返回无效或缓存代理值。
-
smartctl -g wcache /dev/sda:返回Write cache is: disabled或enabled,这是最常用且对 SATA/SAS 普适的判断方式 -
hdparm -I /dev/sda | grep -i write:仅适用于传统 ATA/SATA,输出中*Write cache行带星号表示启用;但 NVMe 或某些 SAS 卡可能不显示 -
sg_modes -p 8,0 /dev/sda:对 SCSI/SAS 设备更底层,需解析输出中第 2 字节 bit 2(WCE 位),但依赖sg3_utils安装且易读错字节偏移
为什么 hdparm -W 查不到或报错
hdparm -W /dev/sda 本质是发 ATA SET FEATURES 命令读取当前写缓存状态,但现代多数 SATA SSD 和部分企业级 HDD 默认禁用该命令响应(出于安全或固件策略),会直接返回 HDIO_DRIVE_CMD(identify) failed: Inappropriate ioctl for device 或空输出。
这不是权限问题,也不是没装 hdparm,而是磁盘固件拒绝暴露该信息。此时别硬试 hdparm -W1 强行开启——可能被忽略,也可能触发设备重置。
- 遇到
Inappropriate ioctl for device,立刻换smartctl -g wcache -
hdparm -W在 NVMe 设备上完全无效,NVMe 使用nvme get-feature -f 0x06(即 Write Cache feature) - 虚拟机里挂载的磁盘(如 VMware vSCSI、QEMU virtio-blk)通常由 hypervisor 控制缓存行为,
hdparm返回的是虚拟层模拟值,不可信
如何验证写缓存实际生效(而不仅是“开了开关”)
开了写缓存 ≠ 数据落盘延迟降低——还要看 I/O 路径是否绕过缓存。常见干扰项:
- 文件系统挂载参数含
sync或barrier=1,会强制每次 write 等待落盘,抵消写缓存效果 - 块设备层启用
queue/dirty_ratio或vm.dirty_background_ratio过低,导致内核频繁刷脏页,掩盖缓存优势 - 使用
O_SYNC或fsync()的应用(如 PostgreSQL、MySQL 默认配置),会跳过 page cache 直接刷盘,写缓存形同虚设
简单验证法:dd if=/dev/zero of=/tmp/test bs=4k count=1000 oflag=direct 测裸盘写速;再去掉 oflag=direct,若后者快 3–10 倍(尤其小块随机写),基本说明写缓存起效。注意:oflag=direct 绕过 page cache,但不绕过磁盘写缓存本身。
容易被忽略的硬件层限制
即使 smartctl 显示 Write cache is: enabled,也不代表你真能用上——某些场景下它会被硬件静默禁用:
- RAID 卡(如 MegaRAID、HBA 模式下的 PERC)默认关闭直通磁盘的写缓存,改由 RAID 卡自身缓存接管;此时查单盘永远显示 disabled
- USB-SATA 桥接芯片(如 JMicron、ASMedia)常屏蔽写缓存控制位,
smartctl返回 always disabled,实测也无加速效果 - 部分 NVMe SSD 在断电保护(PLP)未就绪时(如电容未充电完),固件自动关闭写缓存并锁死开关,
nvme get-feature -f 0x06仍返回 enabled,但性能表现同 disabled
这类情况没有通用命令能 100% 探测,唯一办法是结合 iostat -x 1 观察 await 和 %util:若小块写 await 持续 > 1ms 且 %util 长期 100%,大概率写缓存未生效或被绕过。


















