基本输出插件回调(例如,begin_cb
、change_cb
、commit_cb
和 message_cb
)仅在事务实际提交时调用。更改仍从事务日志中解码,但仅在提交时传递给输出插件(如果事务中止,则会丢弃)。
这意味着,虽然解码是增量发生的,并且可能会溢出到磁盘以控制内存使用,但所有解码的更改都必须在事务最终提交时(或更确切地说,当从事务日志中解码提交时)传输。根据事务的大小和网络带宽,传输时间可能会显著增加应用延迟。
为了减少由大型事务引起的应用延迟,输出插件可以提供额外的回调来支持正在进行的事务的增量流式传输。有多个必需的流式传输回调(stream_start_cb
、stream_stop_cb
、stream_abort_cb
、stream_commit_cb
和 stream_change_cb
)和两个可选回调(stream_message_cb
和 stream_truncate_cb
)。此外,如果要支持两阶段命令的流式传输,则必须提供额外的回调。(有关详细信息,请参见第 49.10 节)。
在对正在进行的事务进行流式处理时,更改(和消息)将通过 stream_start_cb
和 stream_stop_cb
回调分块进行流式处理。一旦所有解码的更改都已传输,就可以使用 stream_commit_cb
回调提交事务(或者可能使用 stream_abort_cb
回调中止事务)。如果支持两阶段提交,则可以使用 stream_prepare_cb
回调准备事务,使用 COMMIT PREPARED
使用 commit_prepared_cb
回调或使用 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 表插入,但未解码主表插入。
即使在流式处理大型事务时,更改仍按提交顺序应用,保留与非流式处理模式相同的保证。