fsync()是PHP 8.1新增函数,用于强制将缓冲区数据及元数据同步至磁盘,解决fwrite()成功后数据仍在内存的问题;它隐式执行fflush()并触发fsync(2)系统调用,返回true表示内核已确认写入请求。

PHP 8.1 中新增的 fsync() 函数,不是“让数据写入磁盘”的起点,而是**强制把已缓冲的数据和元数据真正落盘的关键确认步骤**。它解决的是 fwrite() 成功返回后“数据其实还在内存里”这个常见误解。
为什么 fwrite() 不等于数据已落盘
当你调用 fwrite() 写入文件时:
- 数据先写入 PHP 的用户空间缓冲区(或内核页缓存),不直接触达磁盘
- 操作系统按策略批量刷写(延迟写入、合并 I/O),提升性能但牺牲即时持久性
- 断电、进程崩溃或系统异常时,这部分“看似写完”的数据可能永久丢失
fsync() 做了什么
它作用于一个已打开的文件流(resource),向操作系统发起 fsync(2) 系统调用:
- 隐式执行
fflush():清空 PHP 层缓冲区,把数据送入内核页缓存 - 等待内核将该文件对应的所有脏页(含内容 + 元数据如修改时间、文件大小、inode 信息)写入块设备(如 SSD 或 HDD)
- 函数返回
true表示内核已提交写请求,且收到设备确认(注意:不保证物理介质最终完成写入,但已是应用层可控的最强保障)
怎么正确使用 fsync()
关键不在“用了没”,而在“何时用、怎么用”:
立即学习“PHP免费学习笔记(深入)”;
- 只在业务语义上要求“这次写必须持久化”时调用,比如保存用户关键配置、记录事务日志、生成原子性快照
- 不必每次 fwrite() 后都 fsync();可先批量写入,最后统一调用一次
- 务必检查返回值:
if (!fsync($stream)) { /* 处理错误:磁盘满、设备离线、只读挂载等 */ } - 避免对非普通文件使用(如管道、socket、/proc 下的伪文件),否则会失败
fsync() 和 fdatasync() 的区别
两者都确保数据落盘,但同步范围不同:
- fsync():同步文件内容 + 所有元数据(mtime、ctime、size、权限等)
- fdatasync():仅同步文件数据块,跳过元数据更新(更轻量,适合高频写但不关心时间戳是否落盘的场景)
- Windows 下 fdatasync() 是 fsync() 的别名;POSIX 系统(Linux/macOS)才有实质差异



















