49.9. 用于逻辑解码的大事务的流

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

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

为了减少由大型事务引起的应用时间间隔,输出插件可以提供额外的回调,以支持正在进行的事务的增量流。 这里有多个必需的流回调(stream_start_cb, stream_stop_cb,stream_abort_cb, stream_commit_cbstream_change_cb)和两个可选回调(stream_message_cbstream_truncate_cb)。

当流式处理正在进行的事务时,更改(和消息)以stream_start_cbstream_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

stream_commit_cb(...);  <-- commit of the streamed transaction

当然,回调调用的实际顺序可能更复杂。 可能会有多个流事务的块,一些事务也许会被中止,等等。

与溢出到磁盘的行为类似,流会被触发,当从WAL(对于所有正在进行的事务)解码的更改总数超过logical_decoding_work_mem设置定义的限制时。 此时,最大的顶级事务(通过当前用于解码更改的内存量来衡量)会被选择并流式处理。 然而,在某些情况下,即使启用了流,我们仍然必须溢出到磁盘,因为我们超过了内存阈值,但仍然没有解码完整的元组,例如,只解码toast表插入,但没有主表插入。

即使在流式处理大型事务时,更改仍然按照提交顺序应用,保留了与非流式模式相同的保证。