Postgresql 中文操作指南

49.9. Streaming of Large Transactions for Logical Decoding #

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

这意味着,虽然解码是逐步发生的,并且可能溢出到磁盘以控制内存使用,但是当事务最终提交(或更准确地说,当提交从事务日志解码)时,必须传输所有已解码的更改。根据事务的大小和网络带宽,传输时间可能会显著增加应用延迟。

为了减少由大事务引起的应用滞后,输出插件可能会提供其他回调来支持进行中的事务的增量流。有多个必需的流回调(stream_start_cbstream_stop_cbstream_abort_cbstream_commit_cb_和_stream_change_cb)和两个可选回调(stream_message_cb_和_stream_truncate_cb)。此外,如果要支持两阶段命令流,则必须提供其他回调。(有关详细信息,请参见 Section 49.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 表插入,但没有解码主表插入。

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