2025年9月25日: PostgreSQL 18 发布!
支持的版本: 当前 (18) / 17 / 16 / 15 / 14
开发版本: devel

47.9. 大事务的流式传输以进行逻辑解码 #

基本的输出插件回调函数(例如 begin_cbchange_cbcommit_cbmessage_cb)仅在事务实际提交时调用。更改仍会从事务日志中解码,但仅在提交时传递给输出插件(如果在事务中止时则丢弃)。

这意味着,虽然解码是增量进行的,并且可能为了控制内存使用而溢出到磁盘,但所有解码的更改都必须在事务最终提交时(更准确地说,是在从事务日志中解码提交时)传输。根据事务的大小和网络带宽,传输时间可能会显着增加应用延迟。

为了减少大事务引起的应用延迟,输出插件可以提供额外的回调函数来支持进行中事务的增量流式传输。有多个必需的流式传输回调函数(stream_start_cbstream_stop_cbstream_abort_cbstream_commit_cbstream_change_cb)以及两个可选的回调函数(stream_message_cbstream_truncate_cb)。此外,如果支持两阶段提交命令的流式传输,则必须提供额外的回调函数。(有关详细信息,请参阅第 47.10 节)。

在流式传输进行中的事务时,更改(和消息)会在由 stream_start_cbstream_stop_cb 回调函数分隔的块中流式传输。一旦所有解码的更改都已传输,就可以使用 stream_commit_cb 回调函数提交事务(或者可能使用 stream_abort_cb 回调函数中止事务)。如果支持两阶段提交,则可以使用 stream_prepare_cb 回调函数准备事务,使用 commit_prepared_cb 回调函数执行 COMMIT PREPARED,或者使用 rollback_prepared_cb 回调函数中止事务。

一个事务的流式传输回调函数调用序列示例如下:

stream_start_cb(...);   <-- start of first block of changes
  stream_change_cb(...);
  stream_change_cb(...);
  stream_message_cb(...);
  stream_change_cb(...);
  ...
  stream_change_cb(...);
stream_stop_cb(...);    <-- end of first block of changes

stream_start_cb(...);   <-- start of second block of changes
  stream_change_cb(...);
  stream_change_cb(...);
  stream_change_cb(...);
  ...
  stream_message_cb(...);
  stream_change_cb(...);
stream_stop_cb(...);    <-- end of second block of changes


[a. when using normal commit]
stream_commit_cb(...);    <-- commit of the streamed transaction

[b. when using two-phase commit]
stream_prepare_cb(...);   <-- prepare the streamed transaction
commit_prepared_cb(...);  <-- commit of the prepared transaction

当然,实际的回调函数调用序列可能会更复杂。可能存在多个流式传输事务的块,其中一些事务可能会被中止,等等。

与溢出到磁盘的行为类似,当所有进行中的事务的 WAL 解码更改总量超过 logical_decoding_work_mem 设置定义的限制时,会触发流式传输。此时,将选择占用内存最多的顶级事务(按当前用于解码更改的内存量衡量)并进行流式传输。但是,在某些情况下,即使启用了流式传输,我们仍然需要溢出到磁盘,因为我们超过了内存阈值,但仍未解码完整的元组,例如,仅解码了 toast 表插入但未解码主表插入。

即使在流式传输大事务时,更改仍然按提交顺序应用,保持与非流式传输模式相同的保证。

提交更正

如果您在文档中发现任何不正确、与您在使用特定功能时的体验不符或需要进一步说明的内容,请使用 此表单 来报告文档问题。