受支持版本: 当前版本 (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。此外,如果还要支持两阶段命令的流 式传送,则必须额外提供相关回调。(详见 Section 47.10。)

在流式传送进行中事务时,更改(以及消息)会按由 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


[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 表插入,而没有解码主表插入。

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

提交更正

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