fsync / FlushFileBuffers是否等待未完成的异步IO完成?

问题描述 投票:0回答:1

背景是开发DBMS内核,特别是数据库检查点处理。游戏规则是如此,我们需要在发出fsync()之前等待文件上未完成的异步IO完成。

我们部署的当前解决方案是在运行中手动对异步IO进行计数,在fsync或FlushFileBuffer-ing之前等待此计数变为0。问题是我们是否真的必须这样做,也许内核/文件系统是自己完成的?

有问题的操作系统主要是Windows和Linux,尽管我也很好奇基于BSD的操作系统也是如何处理的。

在Linux上,我们将libaio用于异步IO。

linux-kernel iocp windows-kernel aio fsync
1个回答
0
投票

在Windows上:是,对于给定的HANDLE实例,在执行FlushFileBuffers()之前将清空当前的异步I / O队列。如果您正在编写数据库,则实际上应该使用NtFlushBuffersFileEx(),它提供了更精细的同步粒度,从而产生了巨大的差异。

在FreeBSD上:当然使用ZFS,是的。我不能说我已经测试过UFS,但是如果不一样,我会感到惊讶。在任何情况下,FreeBSD都将缓存的异步I / O作为内核线程池来实现,只有未缓存的异步I / O才是真正的异步。

在Mac OS上:不知道,更糟的是,磁盘I / O语义在最近的几个发行版中就处处可见。与BSD一样,它曾经非常好,但最近已经下坡了。在任何情况下,异步文件I / O在Mac OS上始终几乎无法使用,最大16个深度队列限制加上使用信号进行异步I / O完成的要求很难与线程代码很好地混合。

在Linux上:对于同步I / O,是fsync()强制执行总排序。对于libaio,无论如何它仅对O_DIRECT I / O才真正起作用,我相信块存储层确实会在告知设备进行屏障之前刷新所有排队的I / O,除非您已禁用屏障。对于io_uring(您应该使用它而不是libaio),对于非O_DIRECT I / O,在sqe队列中手动实现的内容之外根本没有排序,即使那样,也就是每个队列,而不是每个索引节点。基本上,io_uring现在对于文件I / O的顺序排序是一团糟(并且我一直与Jens Axboe保持联系,但他没有回复我的电子邮件)。为了使用O_DIRECT I / O进行数据块存储,块存储层是一个单例,并应在整个系统上强制执行排序。因此,只需在sqe队列中对依赖项进行排序,显然它仍然可以与其他队列兼容,但这实际上是可用的。

来源:我是the reference library for the WG21 C++ standardisation of low level i/o的作者。请注意:以上所有内容纯粹是出于我的记忆和经验,可能有些误解或错误。

© www.soinside.com 2019 - 2024. All rights reserved.