如果一个人要在 Linux/Unix 中发出一个由orwrite(2)
分隔的顺序系列,或者是否保证第一个 write() 将在您的第二个 write() 之前提交到磁盘?下面的SO 帖子似乎说不能给出这样的保证,因为涉及多个缓存层。对于保证一致性的数据库系统,这似乎很重要,因为在 WAL(预写日志)恢复中,您需要在实际更改数据之前将日志保存在磁盘上,以便在应用程序/系统发生故障时您可以恢复到上次已知的一致状态。这是如何在实际的数据库系统中确保/实现的?fdatasync(2)
fsync(2)
sync(2)
2 回答
系统sync()
调用实际上没有任何帮助。它承诺安排写入磁盘操作,但仅此而已。
open()
使用的常规技术是在磁盘文件的文件描述符时设置正确的选项: O_DSYNC
, O_RSYNC
, O_SYNC
. 但是,fsync()
和fdatasync()
非常接近相同的效果。您还可以查看O_DIRECTIO
通常支持的内容,尽管 POSIX 根本没有对其进行标准化。
最终,DBMS 依赖于操作系统来保证写入和同步到一个磁盘的数据是安全的。只要设备将始终返回 DBMS 上次写入的内容,即使它由于缓存而不在实际磁盘上(因为它已备份在非易失性缓存或类似的东西中),那么它并不重要. 另一方面,如果您的 NAS(网络附加存储)不能保证您最后写入的内容(并且被告知在磁盘上是安全的)在您阅读时返回,那么您的 DBMS 可能会受到影响,如果它必须这样做恢复。因此,您要谨慎选择存储 DBMS 的位置,确保存储工作正常。如果存储不能像假设的磁盘那样充分工作,您最终可能会丢失数据。
是的,fsync
在现代版本的内核中,既将内存(缓冲区缓存)刷新到磁盘,又将磁盘硬件缓冲区刷新到盘片。手册页说旧内核过去只做第一件事。
描述 fsync() 将文件描述符 fd 引用的文件的所有修改的内核数据(即修改的缓冲区缓存页面)传输(“刷新”)到磁盘设备(或其他永久存储设备)这样即使在系统崩溃或重新启动后,也可以检索所有更改的信息。 这包括写入或刷新磁盘缓存(如果存在)。 呼叫阻塞,直到设备报告传输已完成。它还刷新与文件关联的元数据信息(参见 stat(2))。
旧内核和较少使用的文件系统中的 fsync() 实现不知道如何刷新磁盘缓存。 在这些情况下,需要使用 hdparm(8) 或 sdparm(8) 禁用磁盘缓存以保证安全操作。
这是指应用程序可以请求什么。Fsync 是文件系统提供给应用程序的接口,文件系统本身在下面使用其他东西。文件系统使用屏障,或者更确切地说是显式刷新和 FUA 请求来提交日志。看看LWN 的帖子。