【发布时间】:2019-06-09 23:40:17
【问题描述】:
我有很多数据想以二进制形式保存到磁盘,我想尽可能接近 ACID 属性。由于我有大量数据并且无法将其全部保存在内存中,因此我知道我有两种基本方法:
- 有很多小文件(例如每分钟左右写入磁盘) - 万一发生崩溃,我只会丢失最后一个文件。但是,性能会更差。
- 有一个大文件(例如打开、修改、关闭)- 之后的最佳顺序读取性能,但如果发生崩溃,我最终可能会得到一个损坏的文件。
所以我的问题是:
如果我选择使用大文件选项并将其作为内存映射文件打开(或使用Stream.Position 和Stream.Write),并且断电,是否可以保证可能发生的情况有文件吗?
是否有可能丢失整个大文件,或者只是导致数据在中间损坏?
NTFS 是否确保一定大小(4k?)的块总是被完全写入?
在 Unix/ext4 上的结果是更好还是更差?
我想避免使用 NTFS TxF,因为 Microsoft 已经提到它计划停用它。我正在使用 C#,但语言可能无关紧要。
(补充说明)
似乎应该有一定的保证,因为——除非我错了——如果在写入文件时可能会丢失整个文件(或遭受非常奇怪的损坏),那么现有的数据库将不会是 ACID , 除非他们 1) 使用 TxF 或 2) 在写入之前复制整个文件?如果您丢失了您甚至不打算触摸的部分文件,我认为日记不会帮助您。
【问题讨论】:
-
This thread 有一些关于追加操作的有趣信息,这是主要的操作类型。
-
现有数据库通过三件事实现持久性:1) 在确认操作之前先将所有修改写入事务日志文件,2) 具有允许无缓冲写入存储的操作系统和 3) 具有硬件这保证了如果写入成功,它将被写入物理存储,即使在确认写入后电源应该立即失效。一致性需要更多的工作,但也非常依赖于此。文件系统在这个故事中几乎无关紧要,因为元数据操作(新文件、增长文件)很少见。
-
ACID 的最大敌人,顺便提一下,是商业级硬件,它不提供关键保证 3:保证写入确实已写入。为了提高基准测试中的数字,许多驱动器/控制器会在被要求将某些内容真正写入磁盘时简单地撒谎,并在数据存储在(非电池支持的)缓存中后立即返回。通过这样的设置,软件几乎没有机会确保耐用性——最好希望电源永远不会失效,或者您的数据并不那么重要。这是您为服务器的电池支持 RAID 控制器支付的额外费用。
标签: c# ntfs memory-mapped-files ext4 acid