PostgreSQL码农集散地

PostgreSQL 18 preview - 缓冲区管理器接入异步IO

PostgreSQL 18 preview - 异步IO(AIO)应用到缓冲区管理器层面

PostgreSQL 18 正加紧提交AIO框架和各I/O子系统的实现. 又有几个补丁为 PostgreSQL 的缓冲区管理器引入了异步 I/O (AIO),极大地改变了从磁盘读取数据到内存的方式。

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=50cb7505b3010736b9a7922e903931534785f3aa

aio: Implement support for reads in smgr/md/fd  
author Andres Freund <[email protected]>   
Sat, 29 Mar 2025 17:38:35 +0000 (13:38 -0400)  
committer Andres Freund <[email protected]>   
Sat, 29 Mar 2025 17:38:35 +0000 (13:38 -0400)  
commit 50cb7505b3010736b9a7922e903931534785f3aa  
tree fc507553c57dc1761ab44864146434b5713592ab tree  
parent dee80024688c32fc259a3cff040b609b837a35ec commit | diff  
aio: Implement support for reads in smgr/md/fd  

This implements the following:  

1) An smgr AIO target, for AIO on smgr files. This should be usable not just  
for md.c but also other SMGR implementation if we ever get them.  
2) readv support in fd.c, which requires a small bit of infrastructure work in
   fd.c  
3) smgr.c and md.c support for readv  

There still is nothing performing AIO, but as of this commit it would be  
possible.  

As part of this change FileGetRawDesc() actually ensures that the file is  
opened - previously it was basically not usable. It's used to reopen a file in  
IO workers.  

Reviewed-by: Noah Misch <[email protected]>  
Discussion: https://postgr.es/m/uvrtrknj4kdytuboidbhwclo4gxhswwcpgadptsjvjqcluzmah%40brqs62irg4dt  
Discussion: https://postgr.es/m/[email protected]  
Discussion: https://postgr.es/m/stj36ea6yyhoxtqkhpieia2z4krnam7qyetc57rfezgk4zgapf@gcnactj4z56m  

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=047cba7fa0f8c6930b0dd1d93d98c736ef1e4a5a

bufmgr: Implement AIO read support  
author Andres Freund <[email protected]>   
Sun, 30 Mar 2025 21:28:03 +0000 (17:28 -0400)  
committer Andres Freund <[email protected]>   
Sun, 30 Mar 2025 21:28:03 +0000 (17:28 -0400)  
commit 047cba7fa0f8c6930b0dd1d93d98c736ef1e4a5a  
tree 29feb0de9ab74851134110b04486700444fa3852 tree  
parent ef64fe26bad92a7b8425767cdbbe8b946d4637f0 commit | diff  
bufmgr: Implement AIO read support  

This commit implements the infrastructure to perform asynchronous reads into  
the buffer pool.  

To do so, it:  

- Adds readv AIO callbacks for shared and local buffers  

  It may be worth calling out that shared buffer completions may be run in a  
  different backend than where the IO started.  

- Adds an AIO wait reference to BufferDesc, to allow backends to waitfor
in-progress asynchronous IOs  

- Adapts StartBufferIO(), WaitIO(), TerminateBufferIO(), and their localbuf.c  
  equivalents, to be able to deal with AIO  

- Moves the code to handle BM_PIN_COUNT_WAITER into a helper function, as it  
  now also needs to be called on IO completion  

As of this commit, nothing issues AIO on shared/local buffers. A future commit  
will update StartReadBuffers() to do so.  

Buffer reads executed through this infrastructure will report invalid page /  
checksum errors / warnings differently than before:  

In the error case the error message will cover all the blocks that were  
included in the read, rather than just the reporting the first invalid  
block. If more than one block is invalid, the error will include information  
about the range of the read, the first invalid block and the number of invalid  
pages, with a HINT towards the server logfor per-block details.  

For the warning case (i.e. zero_damaged_buffers) we would previously emit one  
warning message for each buffer in a multi-block read. Now there is only a  
single warning message for the entire read, again referring to the server log
for more details incase of multiple checksum failures within a single larger  
read.  

Reviewed-by: Noah Misch <[email protected]>  
Reviewed-by: Melanie Plageman <[email protected]>  
Reviewed-by: Nazir Bilal Yavuz <[email protected]>  
Discussion: https://postgr.es/m/uvrtrknj4kdytuboidbhwclo4gxhswwcpgadptsjvjqcluzmah%40brqs62irg4dt  
Discussion: https://postgr.es/m/[email protected]  
Discussion: https://postgr.es/m/stj36ea6yyhoxtqkhpieia2z4krnam7qyetc57rfezgk4zgapf@gcnactj4z56m  

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=12ce89fd0708207f21a8888e546b9670a847ad4f

bufmgr: Use AIO in StartReadBuffers()  
author Andres Freund <[email protected]>   
Sun, 30 Mar 2025 22:02:23 +0000 (18:02 -0400)  
committer Andres Freund <[email protected]>   
Sun, 30 Mar 2025 22:02:23 +0000 (18:02 -0400)  
commit 12ce89fd0708207f21a8888e546b9670a847ad4f  
tree 2f96a1a77b53efab20c79ee782a1a1df9b567912 tree  
parent 047cba7fa0f8c6930b0dd1d93d98c736ef1e4a5a commit | diff  
bufmgr: Use AIO in StartReadBuffers()  

This finally introduces the first actual use of AIO. StartReadBuffers() now  
uses the AIO routines to issue IO.  

As the implementation of StartReadBuffers() is also used by the functionsfor
reading individual blocks (StartReadBuffer() and through that  
ReadBufferExtended()) this means all buffered read IO passes through the AIO  
paths.  However, as those are synchronous reads, actually performing the IO  
asynchronously would be rarely beneficial. Instead such IOs are flagged to  
always be executed synchronously. This way we don't have to duplicate a fair  
bit of code.  

When io_method=sync is used, the IO patterns generated after this change are  
the same as before, i.e. actual reads are only issued in WaitReadBuffers() and  
StartReadBuffers() may issue prefetch requests.  This allows to bypass most of  
the actual asynchronicity, which is important to make a change as big as this  
less risky.  

One thing worth calling out is that, if IO is actually executed  
asynchronously, the precise meaning of what track_io_timing is measuring has  
changed. Previously it tracked the time for each IO, but that does not make  
sense when multiple IOs are executed concurrently. Now it only measures the  
time actually spent waiting for IO. A subsequent commit will adjust the docs  
for this.  

While AIO is now actually used, the logic in read_stream.c will often prevent  
using sufficiently many concurrent IOs. That will be addressed in the next  
commit.  

Reviewed-by: Noah Misch <[email protected]>  
Reviewed-by: Nazir Bilal Yavuz <[email protected]>  
Co-authored-by: Andres Freund <[email protected]>  
Co-authored-by: Thomas Munro <[email protected]>  
Discussion: https://postgr.es/m/uvrtrknj4kdytuboidbhwclo4gxhswwcpgadptsjvjqcluzmah%40brqs62irg4dt  
Discussion: https://postgr.es/m/[email protected]  
Discussion: https://postgr.es/m/stj36ea6yyhoxtqkhpieia2z4krnam7qyetc57rfezgk4zgapf@gcnactj4z56m  

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=ae3df4b34155d4a3811762e78d5076e64df66fba

read_stream: Introduce and use optional batchmode support  
author Andres Freund <[email protected]>   
Sun, 30 Mar 2025 22:30:36 +0000 (18:30 -0400)  
committer Andres Freund <[email protected]>   
Sun, 30 Mar 2025 22:36:41 +0000 (18:36 -0400)  
commit ae3df4b34155d4a3811762e78d5076e64df66fba  
tree b31b50ce1fda873657aaa8e08b3ff17075fbb1da tree  
parent f4d0730bbca1b338b8f06389d04816c6c9f06e58 commit | diff  
read_stream: Introduce and use optional batchmode support  

Submitting IO in larger batches can be more efficient than doing so  
one-by-one, particularly for many small reads. It does, however, require  
the ReadStreamBlockNumberCB callback to abide by the restrictions of AIO  
batching (c.f. pgaio_enter_batchmode()). Basically, the callback may not:  
a) block without first calling pgaio_submit_staged(), unless a  
   to-be-waited-on lock cannot be part of a deadlock, e.g. because it is  
   never held while waiting for IO.  

b) directly or indirectly start another batch pgaio_enter_batchmode()  

As this requires care and is nontrivial in some cases, batching is only  
used with explicit opt-in.  

This patch adds an explicit flag (READ_STREAM_USE_BATCHING) to read_stream and  
uses it where appropriate.  

There are two cases where batching would likely be beneficial, but where we  
aren't using it yet:  

1) bitmap heap scans, because the callback reads the VM  

   This should soon be solved, because we are planning to remove the use of  
   the VM, due to that not being sound.  

2) The first phase of heap vacuum  

   This could be made to support batchmode, but would require some care.  

Reviewed-by: Noah Misch <[email protected]>  
Reviewed-by: Thomas Munro <[email protected]>  
Discussion: https://postgr.es/m/uvrtrknj4kdytuboidbhwclo4gxhswwcpgadptsjvjqcluzmah%40brqs62irg4dt  

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=b27f8637ea708c4b6113f0d29a76cb411b430a27

docs: Reframe track_io_timing related docs as wait time  
author Andres Freund <[email protected]>   
Sun, 30 Mar 2025 22:04:40 +0000 (18:04 -0400)  
committer Andres Freund <[email protected]>   
Sun, 30 Mar 2025 22:04:40 +0000 (18:04 -0400)  
commit b27f8637ea708c4b6113f0d29a76cb411b430a27  
tree 08d22f848c612ee7515bcc0a86adcc4430de0db7 tree  
parent 12ce89fd0708207f21a8888e546b9670a847ad4f commit | diff  
docs: Reframe track_io_timing related docs as wait time  

With AIO it does not make sense anymore to track the time for each individual  
IO, as multiple IOs can be in-flight at the same time. Instead we now track  
the time spent *waiting* for IOs.  

This should be reflected in the docs. While, so far, we only do a subset of  
reads, and no other operations, via AIO, describing the GUC and view columns  
as measuring IO waits is accurate for synchronous and asynchronous IO.  

Reviewed-by: Noah Misch <[email protected]>  
Discussion: https://postgr.es/m/5dzyoduxlvfg55oqtjyjehez5uoq6hnwgzor4kkybkfdgkj7ag@rbi4gsmzaczk  

https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=f4d0730bbca1b338b8f06389d04816c6c9f06e58

aio: Basic read_stream adjustments for real AIO
author Andres Freund <[email protected]> 
Sun, 30 Mar 2025 22:26:44 +0000 (18:26 -0400)
committer Andres Freund <[email protected]> 
Sun, 30 Mar 2025 22:26:44 +0000 (18:26 -0400)
commit f4d0730bbca1b338b8f06389d04816c6c9f06e58
tree f1582249bdce5739364cc8849ec368307ed46ac1 tree
parent b27f8637ea708c4b6113f0d29a76cb411b430a27 commit | diff
aio: Basic read_stream adjustments for real AIO

Adapt the read stream logic for real AIO:
- If AIO is enabled, we shouldn't issue advice, but if it isn't, we should
continue issuing advice
- AIO benefits from reading ahead with direct IO
- If effective_io_concurrency=0, pass READ_BUFFERS_SYNCHRONOUSLY to
  StartReadBuffers() to ensure synchronous IO execution

There are further improvements we should consider:

- While in read_stream_look_ahead(), we can use AIO batch submission mode for
  increased efficiency. That however requires care to avoid deadlocks and thus
done separately.
- It can be beneficial to defer starting new IOs until we can issue multiple
  IOs at once. That however requires non-trivial heuristics to decide when to
do so.

Reviewed-by: Noah Misch <[email protected]>
Co-authored-by: Andres Freund <[email protected]>
Co-authored-by: Thomas Munro <[email protected]>

AI 解读

这几个补丁为 PostgreSQL 的缓冲区管理器引入了异步 I/O (AIO),极大地改变了从磁盘读取数据到内存的方式。 让我们逐个分析这些补丁:

补丁 1: aio: Implement support for reads in smgr/md/fd (aio: 在 smgr/md/fd 中实现读取支持)

这个补丁进一步扩展了 AIO 的基础设施,使其能够支持在存储管理器 (smgr)、主数据 (md) 和文件描述符 (fd) 层面的读取操作。 简单来说,它让 PostgreSQL 能够使用 AIO 从磁盘上的文件读取数据。

  • 主要变更:

  1. smgr AIO 目标:  实现了一个 smgr AIO 目标,用于在 smgr 文件上执行 AIO。 这不仅可以用于 md.c,还可以用于我们将来可能拥有的其他 SMGR 实现。  smgr (Storage Manager) 是 PostgreSQL 中负责管理底层存储的模块。  这个目标定义了如何使用 AIO 与 smgr 文件进行交互。
  2. fd.c 中的 readv 支持: 在 fd.c 中添加了 readv 支持,这需要在 fd.c 中进行一些小的基础设施工作。  fd.c 负责处理文件描述符相关的操作。  readv 允许从多个缓冲区读取数据到单个内存位置,提高效率。
  3. smgr.c 和 md.c 对 readv 的支持:  在 smgr.c 和 md.c 中添加了对 readv 的支持。  md.c 负责处理主数据(例如表数据)。
  • 重要事项:

    • 尚未实际执行 AIO:  与之前的补丁类似,这个补丁只是提供了基础设施。  目前还没有任何代码实际执行 AIO 读取操作。  但是,从这个补丁开始,理论上 已经可以执行 AIO 了。
    • FileGetRawDesc() 的改进:  作为此更改的一部分,FileGetRawDesc() 实际上确保文件已打开。 以前,它基本上不可用。 它用于在 I/O 工作进程中重新打开文件。  这是一个重要的修复,因为它确保了在 I/O 工作进程中使用 FileGetRawDesc() 是可靠的。

    更详细的解释:

    • smgr (存储管理器):  PostgreSQL 使用存储管理器来抽象底层存储。 这允许 PostgreSQL 支持不同的存储后端,而无需更改核心代码。  这个补丁为 smgr 添加了 AIO 支持,这意味着任何使用 smgr 的代码都可以利用 AIO 来提高 I/O 性能。
    • md (主数据):  主数据是指存储实际表数据的文件。  这个补丁为 md 添加了 AIO 支持,这意味着 PostgreSQL 可以使用 AIO 从表数据文件中读取数据。
    • fd (文件描述符):  文件描述符是操作系统用来引用打开文件的整数。  这个补丁为 fd 添加了 readv 支持,这意味着 PostgreSQL 可以使用 readv 从多个文件描述符读取数据到单个内存位置。

    总结:

    这个补丁是 AIO 支持的又一个构建块。 它扩展了 AIO 的基础设施,使其能够支持在 smgr、md 和 fd 层面的读取操作。 虽然它还没有实际执行 AIO,但它为未来的 AIO 实现奠定了基础。  FileGetRawDesc() 的修复也提高了 I/O 工作进程的可靠性。

    补丁 2: bufmgr: Implement AIO read support (bufmgr: 实现 AIO 读取支持)

    这个补丁为 AIO 奠定了基础。 它实际上 还没有使用 AIO,但它建立了必要的基础设施。 可以把它想象成在开车之前先修路和桥。

    • 主要变更:

      • AIO 回调函数: 为共享缓冲区和本地缓冲区添加了 readv AIO 回调函数。 readv 允许从多个缓冲区读取数据到单个内存位置,这比单独读取每个缓冲区更有效。 关键是,它指出共享缓冲区的完成可能发生在与 I/O 启动不同的后端进程中。 这对于理解并发的影响非常重要。
      • BufferDesc AIO 等待引用: 引入了一种机制,允许后端等待缓冲区上正在进行的异步 I/O 操作。 这对于确保数据一致性至关重要。
      • 适配现有函数: 修改了 StartBufferIO()、WaitIO()、TerminateBufferIO() 及其本地缓冲区等效函数,以处理 AIO。 这些函数是缓冲区管理系统的核心,因此它们需要了解 I/O 的新异步特性。
      • BM_PIN_COUNT_WAITER 的辅助函数: 将处理 BM_PIN_COUNT_WAITER 标志的代码移动到一个辅助函数中。 此标志指示进程正在等待缓冲区的 pin 计数降至零。 现在在 I/O 完成时也需要这样做。
      • 错误处理变更: 显著改变了页面/校验和错误的报告方式。 现在,它报告多块读取中的所有无效块,而不是仅报告第一个无效块。 这提供了更全面的错误信息。 它还整合了 zero_damaged_buffers 的警告消息,以避免垃圾信息塞满日志。
    • 重要事项:

      • 尚未实际使用 AIO: 此补丁仅提供 基础设施。 没有执行实际的异步读取。
      • 错误报告改进: 对错误和警告报告的更改是一项重大改进,提供了更多上下文并减少了日志噪音。

    补丁 3: bufmgr: Use AIO in StartReadBuffers() (bufmgr: 在 StartReadBuffers() 中使用 AIO)

    这个补丁最终将 AIO 基础设施投入使用。 它修改了 StartReadBuffers() 以启动异步 I/O。

    • 主要变更:

      • StartReadBuffers() 中的 AIO:StartReadBuffers() 现在使用 AIO 例程来发出 I/O 请求。
      • 同步回退: 对于同步读取(例如,当 io_method=sync 时),I/O 被标记为同步执行。 这避免了重复代码,并允许更安全地过渡到 AIO。 这是一个关键点:该补丁旨在在不需要 AIO 时尽量减少破坏性。
      • 对 track_io_timing 的影响:track_io_timing 的含义发生了变化。 以前,它测量每个单独的 I/O 操作的时间。 现在,它测量 等待 I/O 操作完成所花费的时间。 这是因为使用 AIO 时,可以同时进行多个 I/O 操作。
    • 重要事项:

      • 首次真正使用 AIO: 这是第一个实际使用 AIO 的补丁。
      • 同步兼容性: 该补丁旨在与同步 I/O 一起使用,从而最大限度地降低引入回归的风险。
      • track_io_timing 变更: 对于监控和性能分析,需要注意 track_io_timing 含义的变更。
      • read_stream.c 瓶颈: 该补丁承认 read_stream.c 可能会限制并发 I/O 操作的数量,这将在未来的补丁中解决。

    补丁 4: read_stream: Introduce and use optional batchmode support (read_stream: 引入并使用可选的批处理模式支持)

    此补丁将批处理引入 read_stream 代码,允许将多个 I/O 请求一起提交,以提高效率。

    • 主要变更:

      • 批处理支持: 添加了一个 READ_STREAM_USE_BATCHING 标志,以启用 read_stream 中的批处理。
      • AIO 批处理限制: 强调了 AIO 批处理施加的限制,特别是对 ReadStreamBlockNumberCB 回调中阻塞和嵌套批处理的限制。
      • 选择性批处理: 由于涉及的复杂性,批处理仅在显式选择加入的情况下使用。
      • 未来改进: 确定了两个批处理可能有利但尚未实现的领域:位图堆扫描和堆 vacuum 的第一阶段。
    • 重要事项:

      • 效率提升: 批处理可以显著提高 I/O 性能,尤其是在小读取的情况下。
      • 复杂性: AIO 批处理引入了需要仔细考虑的复杂性。
      • 未来优化: 该补丁确定了未来优化的潜在领域。

    补丁 5: docs: Reframe track_io_timing related docs as wait time (docs: 将 track_io_timing 相关文档重新定义为等待时间)

    此补丁更新了文档,以反映 track_io_timing 含义的变更。

    • 主要变更:

      • 文档更新: 重新定义了 track_io_timing 和相关视图列的文档,将其描述为测量 I/O 等待 时间,而不是每个单独的 I/O 操作的时间。
    • 重要事项:

      • 准确性: 确保文档准确地反映了 AIO 上下文中 track_io_timing 的行为。

    总体总结和影响:

    这些补丁通过引入 AIO 代表了对 PostgreSQL I/O 性能的重大改进。 以下是主要要点的总结:

    • 性能提升: AIO 允许 PostgreSQL 同时执行多个 I/O 操作,这可以显著减少从磁盘读取数据所需的时间。
    • 延迟降低: 通过将 I/O 操作与其他任务重叠,AIO 可以降低总体延迟。
    • 吞吐量增加: AIO 可以通过允许系统同时处理更多 I/O 请求来增加系统的总体吞吐量。
    • 复杂性: AIO 引入了需要仔细考虑的复杂性,例如管理异步操作和处理错误的需求。
    • 逐步采用: 这些补丁旨在逐步采用,并在必要时能够回退到同步 I/O。
    • 监控变更:track_io_timing 含义的变更需要调整监控和性能分析。

    总而言之,这些补丁使 PostgreSQL 的 I/O 子系统现代化,使其更高效、更灵敏。 逐步的方法和对同步兼容性的仔细考虑使这成为一项精心设计的变更。 批处理的引入进一步增强了 AIO 的优势。 文档更新确保用户了解 track_io_timing 的新行为。

    补丁 6: aio: Basic read_stream adjustments for real AIO (aio: 为真正的 AIO 进行基本的 read_stream 调整)

    这个补丁对 read_stream 逻辑进行了一些基本的调整,以更好地支持真正的 AIO (Asynchronous I/O)。 之前的补丁主要构建了 AIO 的基础设施,而这个补丁开始针对 AIO 的实际使用进行优化。

    • 主要变更:

      • 如果启用了 AIO: 不应该发出建议 (advice)。
      • 如果未启用 AIO: 应该继续发出建议 (advice)。
      • 这里的 "建议 (advice)" 指的是 posix_fadvise 系统调用,它允许程序向操作系统提供关于文件访问模式的提示,以便操作系统可以优化 I/O 操作。  当使用 AIO 时,操作系统已经能够更好地管理 I/O 操作,因此不再需要程序提供额外的建议。
      • 禁用建议 (Advice) 的逻辑:
      • 直接 I/O (Direct IO) 的预读 (Read Ahead) 优势:  AIO 从使用直接 I/O 进行预读中获益。  直接 I/O 绕过了操作系统的页面缓存,允许程序直接从磁盘读取数据。  这对于 AIO 来说是有利的,因为它可以减少 I/O 操作的延迟。
      • effective_io_concurrency=0 的处理:  如果 effective_io_concurrency=0,则将 READ_BUFFERS_SYNCHRONOUSLY 传递给 StartReadBuffers(),以确保同步 I/O 执行。  effective_io_concurrency 是一个 PostgreSQL 配置参数,用于控制并发 I/O 操作的数量。  如果将其设置为 0,则意味着禁用并发 I/O,因此需要确保 I/O 操作以同步方式执行。
    • 未来改进的考虑:

      • read_stream_look_ahead() 中的 AIO 批处理提交模式:  在 read_stream_look_ahead() 中,可以使用 AIO 批处理提交模式来提高效率。  但是,这需要小心避免死锁,因此需要单独处理。  read_stream_look_ahead() 是 read_stream 模块中的一个函数,用于预取数据。
      • 延迟启动新 I/O 直到可以一次发出多个 I/O:  延迟启动新的 I/O 操作,直到可以一次发出多个 I/O 操作,这可能是有益的。  但是,这需要使用复杂的启发式方法来决定何时这样做。

    更详细的解释:

    • posix_fadvise (文件访问建议):posix_fadvise 是一个系统调用,允许程序向操作系统提供关于文件访问模式的提示。  这些提示可以帮助操作系统优化 I/O 操作,例如预读数据或将数据缓存到内存中。  但是,在使用 AIO 时,操作系统已经能够更好地管理 I/O 操作,因此不再需要程序提供额外的建议。
    • 直接 I/O (Direct IO):  直接 I/O 绕过了操作系统的页面缓存,允许程序直接从磁盘读取数据。  这对于 AIO 来说是有利的,因为它可以减少 I/O 操作的延迟。  但是,直接 I/O 也有一些缺点,例如它可能会增加 CPU 的使用率。
    • effective_io_concurrency:effective_io_concurrency 是一个 PostgreSQL 配置参数,用于控制并发 I/O 操作的数量。  如果将其设置为 0,则意味着禁用并发 I/O,因此需要确保 I/O 操作以同步方式执行。

    总结:

    这个补丁对 read_stream 逻辑进行了一些基本的调整,以更好地支持真正的 AIO。 它解决了在使用 AIO 时的一些常见问题,例如禁用建议 (advice) 的逻辑和处理 effective_io_concurrency=0 的情况。  此外,它还提出了未来改进的考虑,例如在 read_stream_look_ahead() 中使用 AIO 批处理提交模式和延迟启动新 I/O 直到可以一次发出多个 I/O 操作。  总的来说,这个补丁是 AIO 支持的一个重要步骤,它使 PostgreSQL 能够更好地利用 AIO 来提高 I/O 性能。