【发布时间】:2015-07-29 20:25:55
【问题描述】:
我想自动覆盖文件的内容。在覆盖配置文件时,我需要它来保持完整性,因此更新应该通过或失败,并且永远不要让文件写一半或损坏。
我经历了多次迭代来解决这个问题,这是我目前的解决方案。
覆盖文件“foo.config”的步骤:
- 输入一个全局互斥锁(每个文件名唯一)
- 在“foo.config.tmp”中写入新内容
- 在关闭文件之前在文件句柄上调用FlushFileBuffers 以刷新操作系统文件缓冲区
- 致电ReplaceFile 将在内部
- 将“foo.config”重命名为“foo.config.bak”
- 将“foo.config.tmp”重命名为“foo.config”
- 删除“foo.config.bak”
- 释放全局互斥体
我认为这个解决方案很强大,但是在电源故障后,这个可怕的问题在生产中再次出现。发现配置文件已损坏,以“NULL”字符填充,.tmp 或 .bak 文件不存在。
我的理论是删除“foo.config.bak”时原始文件内容被清零,但由 ReplaceFile 调用引起的文件系统元数据更新没有刷新到磁盘。所以重启后,“foo.config”指向的是已经清零的原始文件内容,这是否可能因为在DeleteFile之前调用了ReplaceFile?
文件存储在 SSD (SanDisk X110) 上。
您是否发现我的文件覆盖程序存在缺陷?会不会是 SSD 的硬件故障?即使在断电的情况下,您是否有保证文件覆盖的原子性的想法?理想情况下,我想在覆盖后删除 tmp 和 bak 文件。
谢谢,
【问题讨论】:
-
删除文件不会将内容归零。我认为写入 foo.config.tmp 的数据更有可能从未到达磁盘,可能是因为 SSD 内部的缓存,或者文件系统本身可能已损坏并且在自我修复过程中数据丢失。尽管关闭写入缓存(通过设备管理器)可能会有所帮助,但确实没有任何可靠的方法可以防止断电导致此类问题。其他建议是用于服务器的电池备份磁盘和/或 UPS。
-
您的 ReplaceFile 方法看起来不错,但在您和磁盘(或 SSD)之间存在各种代码,在断电时可能无法达到您的预期。 (我知道至少有一个硬盘会很高兴地告诉操作系统它的所有缓存都已被刷新,而实际上它们并没有。)我强烈建议使用不间断电源。
标签: windows file-io corruption