2 回答
TA贡献1829条经验 获得超9个赞
您可以调用FlushViewOfFile
,它启动脏页写入,然后FlushFileBuffers
,根据本文,它保证页面已被写入。
每次写入后调用FlushFileBuffers
可能“更安全”,但不建议这样做。你必须知道你能承受多少损失。有一些模式可以限制这种潜在的损失,即使是最好的数据库也可能遭受写入失败。您只需要以尽可能少的损失恢复生活,这通常需要一些多阶段提交的日志记录。
我想可以打开内存映射文件, FILE_FLAG_NO_BUFFERING
但这FILE_FLAG_WRITE_THROUGH
会消耗你的吞吐量。我不这样做。我为异步 I/O 打开内存映射文件,让操作系统通过它自己的异步 I/O 完成端口实现来优化吞吐量。这是最快的吞吐量。我可以容忍潜在的损失,并已适当减轻。我的内存映射数据是文件备份数据......如果我检测到丢失,一旦硬件错误被清除,我可以检测并重新备份丢失的数据。
显然,文件系统必须足够可靠才能运行数据库应用程序,但我不知道有任何供应商建议您仍然不需要备份。坏事会发生。计划损失。我做的一件事是我从不写入数据中间。我的数据是不可变的和版本化的,每个“数据”文件限制为 2gb,但每个应用程序采用不同的策略。
TA贡献1871条经验 获得超8个赞
NTFS 文件系统(和 ext3-4)使用事务日志来操作更改。每个更改都存储在日志中,然后日志本身用于有效地执行更改。除了灾难性的磁盘故障外,文件系统被设计为在其自己的数据结构中保持一致,而不是您的:在崩溃的情况下,恢复过程将决定回滚什么以保持一致性。在回滚的情况下,您的“尚未写入但要写入”的数据将丢失。文件系统将是一致的,而您的数据则不是。
此外,还涉及其他几个因素:软件和硬件缓存引入了一个额外的层,因此是一个故障点。通常操作是在缓存中执行的,然后缓存本身会刷新到磁盘上。文件系统驱动程序不会看到“在”缓存中执行的操作,但我们会看到刷新操作。这样做是出于性能原因,因为硬盘是瓶颈。硬件控制器确实有电池,以保证即使在断电的情况下也可以刷新自己的缓存。
扇区的大小是另一个重要因素,但不应考虑此细节,因为出于互操作性目的,硬盘驱动器本身可能与其原始大小有关。
如果你有一个 mewmory 映射并且你在中间插入数据,当电源关闭时,如果文件的内容超过了内部缓冲区的大小,则文件的内容可能部分包含你所做的更改。
TxF 是一种缓解问题的方法,但有几个影响限制了您可以使用它的上下文:例如,它不适用于不同的驱动器或共享网络。
为了成为 ACID,你需要设计你的数据结构和/或你使用它的方式,以免依赖于实现细节。例如,Mercurial(版本控制工具)总是将自己的数据附加到自己的修订日志中。有许多可能的模式,但是,您需要的保证越多,您获得的技术就越具体(并且与之相关)。
- 2 回答
- 0 关注
- 131 浏览
添加回答
举报