我正在研究现实世界中的多用户文件存储系统 该系统必须面对系统崩溃或电源事件 失败,所以我正在研究一致性和耐久性。
许多数据库系统都支持ACID和现代计算机系统 支持日记文件系统。我注意到了一个日志系统 对于这样的系统来说非常重要,我们可以使用测井系统 弄清楚发生了什么事以及事故发生前没有发生的事情, 因此,当系统重新启动时,我们可以做一个合适的恢复工作。
典型的日志系统工作步骤:
因此,当系统崩溃事件发生时,只有几种可能性:
某些日记文件系统就是这样工作的。
我一般都不知道数据库系统是如何工作的 数据库系统是在用户空间运行的软件,据我所知, 文件写入功能和磁盘之间有几个东西 面:
因此,当函数返回时,数据可能不在磁盘上,也可能不在 在这些缓存中。
在Windows系统上,可以通过FILE_FLAG_NO_BUFFERING禁用缓存 当CreateFile,MSDN表示#34;当禁用缓存时,全部读取 和写操作直接访问物理磁盘",我的第一个 问题是,FILE_FLAG_NO_BUFFERING是否关闭磁盘缓存为 好 ?或者如何确保数据已到达磁盘表面 ?
还有一个问题:SATA和SCSI磁盘正在使用"命令 排队"技术,队列中的命令可以重新排序 更有效地处理,但日志系统依赖于 time-order,命令排队对于日志记录系统(用户空间)是不是很糟糕? 或者我怎样才能确定在B之前写过A?
答案 0 :(得分:2)
以崩溃安全的方式覆盖数据的基本方法是:
fsync
功能的内容将上述内容刷新到稳定存储。这是为了刷新缓存和所有内容,以便在函数返回时,数据实际上是在磁盘上。刷新用作write barriers:它们确保刷新之前的所有内容都安全地存储在磁盘上,然后才能写入刷新之后的任何内容。 在之间存在一对障碍,写入的重新排序(例如,由于具有命令排队的磁盘)不是问题,因为障碍确保订单在其重要的地方是正确的。在步骤1中,您不关心磁盘在写入前半部分之前是否物理写入文件的后半部分;你只关心整个文件是在日记条目之前写的,证明新文件已经完成。
崩溃后,您将查看日记并处理每个条目:
您可能会发现阅读PostgreSQL's documentation on reliability and write-ahead logging(这是PostgreSQL关于上述日记记录机制的术语)的信息。它包含了额外的安全措施,例如WAL(日志)条目的校验和以防止损坏,在正常操作期间,磁盘刷新被推迟和批处理以获得更好的性能(以崩溃恢复可能需要更长的时间为代价)。
然而,谈到数据库,实际上使用实际上可能更容易和更安全 - 它具有强大且经过良好测试的一致性和持久性机制 - 而不是试图自己推出。如果像PostgreSQL这样的完整数据库服务器对于您的应用程序来说太重了,可以考虑使用像SQLite或Berkeley DB那样轻松的东西(这是一个低级键值存储,而不是SQL关系数据库)。 Both支持atomic commits。