【问题标题】:Is write/fwrite guaranteed to be sequential?write/fwrite 是否保证是连续的?
【发布时间】:2015-04-25 05:33:28
【问题描述】:

通过write(或fwrite)写入的数据是否保证按顺序持久化到磁盘?特别是在容错方面。如果系统在写入过程中发生故障,它是否会表现得好像首先写入第一个字节并且写入中途停止(而不是写入随机块)。

另外,对write/fwrite 的连续调用是否保证是连续的?根据 POSIX,我发现只有调用 read 才能保证考虑以前的 write

我问的是我正在创建一个持久保存到磁盘的容错数据存储。我的写作逻辑顺序是这样的,错误不会破坏数据,但如果不遵守逻辑顺序,我就有问题了。

注意:我不是在问是否保证持久性。只有当我的写作呼吁最终坚持下去时,他们才会遵守我实际写作的顺序。

【问题讨论】:

  • 您介意更详细地定义“fail”吗? EIO,还是什么?
  • @alk 任何故障,程序突然中止,断电,冻结。只是阻止将挂起的磁盘写入刷新到磁盘的任何东西。
  • 我认为没有这样的保证。

标签: c posix libc


【解决方案1】:

The POSIX docs for write() 声明“如果已设置 O_DSYNC 位,则文件描述符上的写入 I/O 操作应按照同步 I/O 数据完整性完成的定义完成”。据推测,如果O_DSYNC 位未设置,则未指定 I/O 数据完整性完成的同步。 POSIX 还说“这卷 POSIX.1-2008 也对应用程序级缓存的任何影响(例如 stdio 所做的)保持沉默”,所以我认为不能保证fwrite()

【讨论】:

  • 我看了但找不到“同步 I/O 数据完整性”的定义,除了说它是同步写入的。同步写入实际上并不是我真正想要的,我只想要一个有保证的写入顺序(我不在乎它是否真的写了所有东西)。
  • 简而言之,dsync 语义与手头的问题无关。
【解决方案2】:

我不是专家,但我可能知道的足够多,可以为您指明正确的方向:

最灾难性的情况是如果你失去了权力,那么这是唯一值得考虑的情况。

  • 从一个包含 X 字节有意义内容的文件开始,并带有一个标头。
  • 在不会使 X 失效的地方写入 Y 字节有意义的内容。
  • 致电fsync(慢!)。
  • 更新标头(可能必须小于磁盘的块大小)。

我不知道更改文件的长度是否安全。我不知道在多大程度上取决于文件系统挂载模式,除了任何“安全”模式都可能完全不可用,因为系统需要甚至有轻微的性能水平。

请记住,在某些系统上,fsync 调用是谎言并且只是返回而没有安全地执行任何操作。你可以说出来,因为它很快就会回来。因此,您需要进行相当大的事务(即比应用程序级事务大得多)。

请记住,在现实世界中解决此问题的人至少会获得 6 位数的高薪。对于我们其他人来说,最好的答案是“只需将数据发送到 postgres 并让它处理它”。或“接受我们可能不得不丢失数据并恢复到每小时备份。”

【讨论】:

  • 我正在寻找一个我不必依赖fsync 的解决方案。我不需要同步写入,只需要某种顺序保证(这听起来可能是不可能的)。
  • @edA-qamort-ora-y 您可以尝试man ext4 或任何您的文件系统,并查看诸如data=orderedauto_da_alloc 之类的选项。请注意,无论手册页调用什么“默认值”,都可能不是您在系统上实际使用的,即使您在 fstab 中没有任何选项。
  • @edA-qamort-ora-y Fsync 不会使写入同步,而是在更新标头之前充当屏障。由于原子扇区写入,标头应该正好是 512 字节。
  • Fsync 过去常说谎,或者称之为“改变语义”。以前 fsync 只从内存缓冲区推送到磁盘。如果磁盘也在缓冲写入,那么无论如何您都没有安全性。新内核正确地将磁盘缓冲区推送到盘片。查看man fsync
【解决方案3】:

不,一般而言,就 POSIX 和现实而言,文件系统不提供此类保证。持久性的顺序(磁盘使它们永久保存在盘片上)不受系统调用的顺序、文件中的位置或磁盘上扇区的顺序决定。文件系统将要写入内存的数据保留几秒钟,尽可能地囤积,然后以它们看起来合适的任何顺序将它们分批发送到磁盘。而且无论内核如何将其发送到磁盘,由于 NCQ,磁盘本身都可以自行重新排序写入。

文件系统有确保一些顺序的安全性。过去使用了屏障,现在使用了显式刷新和 FUA 请求。对此有一个很好的article on LWN。但这些是由文件系统使用的,而不是应用程序。

我强烈建议阅读有关Application Level Consistency 的文章。不确定与您的相关性如何,但它显示了开发人员过去错误假设的许多行为。

o11c 的回答是一个很好的方法。

【讨论】:

    【解决方案4】:

    是的,只要我们不是在谈论增加多线程的复杂性。它将在磁盘上以相同的顺序排列,以使其成为磁盘。它缓冲到内存,并在内存填满或关闭文件时将该内存转储到磁盘。

    【讨论】:

    • 您是否参考了表明此保证的标准或帮助页面?
    • 一般来说,持久化顺序和磁盘布局都不能保证。
    • OP 没有询问磁盘上的布局,只是询问他在读取时获得的数据的顺序。
    猜你喜欢
    • 2011-02-19
    • 2010-10-25
    • 1970-01-01
    • 1970-01-01
    • 2012-04-03
    • 2012-07-09
    • 2014-01-21
    • 1970-01-01
    相关资源
    最近更新 更多