代码之家  ›  专栏  ›  技术社区  ›  xyzzyrz

是否可以在每次提交时使用单个fsync实现日志记录?

  •  2
  • xyzzyrz  · 技术社区  · 15 年前

    假设您正在构建日志记录/提前写入日志记录存储系统。您可以通过(对于每个事务)附加数据(使用write(2))、附加提交标记然后fsync来实现这一点吗?

    要考虑的场景是,如果您对这个日志进行大量的写入,然后fsync它,就会出现故障。 在fsync期间 . inode直接/间接块指针是否仅在刷新所有数据块后刷新,或者是否没有保证按顺序刷新块?如果是后者,那么在恢复过程中,如果在文件末尾看到提交标记,就不能相信它与前一个提交标记之间的数据是有意义的。因此,您必须依赖另一种机制(至少涉及另一个fsync)来确定日志文件的一致性程度(例如,写入/fsynching数据,然后写入/fsynching提交标记)。

    如果有区别,主要是想知道ext3/ext4作为上下文。

    2 回复  |  直到 15 年前
        1
  •  4
  •   Russell Sears    15 年前

    请注意,默认情况下,Linux和Mac OS的fsync和fdatasync不正确。默认情况下,Windows是正确的,但可以为了基准测试而模拟Linux。

    此外,如果附加到文件结尾,fdatasync会发出多个磁盘写入,因为它需要用新的长度更新文件inode。如果您希望每次提交一次写入,最好的办法是预先分配日志空间,在提交标记中存储一个日志条目的CRC,并在提交时发出一个FDataSync()。这样,无论操作系统/硬件在背后重新排序多少,您都可以找到实际命中磁盘的日志的前缀。

    如果您想使用日志进行持久提交或提前写入,事情会变得更加困难,因为您需要确保fsync实际工作。在Linux下,您将希望使用hdparm禁用磁盘写缓存,或者使用barrier设置为true安装分区。[编辑:我坚持更正,屏障似乎没有给出正确的语义。SATA和SCSI引入了许多原语,例如写屏障和本机命令队列,使操作系统能够导出启用提前写入日志记录的原语。从我从manpages和在线上可以看出,Linux只向文件系统开发人员公开这些内容,而不向用户空间公开。]

    自相矛盾的是,禁用磁盘写缓存有时会导致更好的性能,因为您可以在用户空间中获得对写调度的更多控制;如果磁盘对一系列同步写请求进行排队,则最终会向应用程序暴露奇怪的延迟峰值。禁用写缓存可以防止这种情况发生。

    最后,实际系统使用group commit,并在并发工作负载下对每个commit执行<1同步写入。

        2
  •  1
  •   caf    15 年前

    无法保证块刷新到磁盘的顺序。如今,即使是驱动器本身也可以在去盘片的路上重新订购块。

    如果要强制执行排序,至少需要 fdatasync() 在您要订购的写入之间。所有的同步承诺都是 当它回来时 ,在同步到达存储之前写入的所有内容。

    推荐文章