如何保证所有数据都已物理写入磁盘?
据我了解,.NET FileStream 的 Flush 方法仅将当前缓冲区写入磁盘,但依赖于 Windows 的磁盘驱动程序和硬盘固件,这不能保证数据实际上物理写入磁盘。
有没有 .NET 或 Win32 方法可以给我这样的保证? 因此,如果在调用此方法返回后一纳秒断电,我仍然可以确定一切正常吗?
I understand that .NET FileStream's Flush method only writes the current buffer to disk, but dependent on Windows' disk driver and the hard disk firmware this is no guarantee that the data is actually physically written to disk.
Is there a .NET or Win32 method that can give me this guarantee? So if there is power loss one nanosecond after the call to this method comes back, I can still be sure that everything is OK?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
斯特凡·S. 说:
不,.NET FileStream 的 Flush 只将 .NET 缓冲区写入操作系统缓存,它不会将操作系统缓存刷新到磁盘。 遗憾的是,MSDN 文档中关于此类的内容并没有这么说。 对于.NET< 4.0 中,您必须调用 Flush + Win32 的 FlushFilebuffers:
对于 .NET 4.0,您可以使用新的 flash(true) 方法。
2012 年 11 月 9 日更新:MS 错误报告 这里 说它已损坏,然后修复,但没有说明修复的版本或服务包! 听起来好像 bug 是如果内部 .NET FileStream 缓冲区为空,则 Flush(true) 不会执行任何操作?
Stefan S. said:
No, .NET FileStream's Flush only writes the .NET buffers to the OS cache, it does not flush the OS cache to disk. Sadly the MSDN doc on this class doesn't say that. For .NET < 4.0, you'll have to call Flush + Win32's FlushFilebuffers:
For .NET 4.0, you can instead use the new flush(true) method.
11/09/2012 update: MS bug report here says it's broken, then fixed, but doesn't say what version or service pack it was fixed in! Sounds like bug was if internal .NET FileStream buffer is empty, the Flush(true) did nothing??
在 Windows 下,查看 FlushFileBuffers ( Win32 API)。
Under Windows, look at FlushFileBuffers (Win32 API).
好吧,你可以关闭该文件......这可能会做到这一点。 事实上,随着 HAL 抽象、虚拟化和磁盘硬件现在比几年前的计算机拥有更多的处理能力和缓存,您将不得不忍受希望磁盘完成其工作的希望。
事务性文件系统从未真正实现;-p 当然,您也许可以考虑使用数据库作为后端,并使用其事务系统?
另外:请注意,并非所有流都保证
Flush()
- 例如,GZipStream
等即使在刷新之后也会保留未提交数据的工作缓冲区 - 这是获得的唯一方法要刷新一切就是Close()
它。Well, you could close the file... that would probably do it. In reality, with HAL abstraction, virtualization, and disk hardware now having more processing power and cache memory than computers did a few years ago, you're going to have to live with hoping the disk does its job.
The transactional file system never really materialized ;-p Of course, you could perhaps look at using a database as a back end, and use the transaction system of that?
Aside: note that not all streams even guarantee to
Flush()
- for example,GZipStream
etc retain a working buffer of uncommitted data even after a flush - the only way to get it to flush everything is toClose()
it.我注意到 .NET 4 #Flush(true) 实际上并没有写入磁盘。 我们遇到了数据损坏的奇怪问题,我发现了这个 错误报告:
错误报告的详细信息选项卡有一个测试程序,您可以运行该程序来显示问题;
fs.Flush(true)
。 这不需要时间(比写入磁盘的速度快得多)。FlushFileBuffers
。 这需要很长时间。我正在切换到 win32 FlushFileBuffers 调用...
I've noticed that the .NET 4 #Flush(true) doesn't actually write to the disk. We were having strange issues with corrupted data and I found this bug report on the MS site:
The details tab for the bug report has a test program you can run that will show the issue;
fs.Flush(true)
. This takes no time (much faster than can possibly written to the disk).FlushFileBuffers
. This takes a long time.I'm changing over to the win32 FlushFileBuffers call...
文件系统缓存中缓冲的文件数据将写入磁盘。 该数据通常是根据磁盘写入头的位置延迟写入的。 拥有千兆字节的缓存数据在技术上是可行的,因此可能需要相当长的时间。 如果这对您很重要,那么请考虑使用 FileOptions.WriteThrough 选项。
The file data that's buffered in the file system cache to be written to disk. That data is normally lazily written, based on the position of the disk write head. Having a gigabyte of cached data is technically possible so it can take quite a while. If this is important to you then consider the
FileOptions.WriteThrough
option instead.抽象级别太多,无法绝对确保数据写入光盘,一直到硬件级别。
性能不是很好,也不是万无一失,但是在单独的进程中写入文件后重新打开文件并检查大小或内容怎么样?
There's simply too many levels of abstraction to be absolutely sure that the data is written to the disc, right down to the hardware level.
Not brilliantly performant or foolproof, but how about re-opening the file once it is written in a seperate process and checking the size or contents?