2 47.9. Streaming of Large Transactions for Logical Decoding #
4 The basic output plugin callbacks (e.g., begin_cb, change_cb, commit_cb
5 and message_cb) are only invoked when the transaction actually commits.
6 The changes are still decoded from the transaction log, but are only
7 passed to the output plugin at commit (and discarded if the transaction
10 This means that while the decoding happens incrementally, and may spill
11 to disk to keep memory usage under control, all the decoded changes
12 have to be transmitted when the transaction finally commits (or more
13 precisely, when the commit is decoded from the transaction log).
14 Depending on the size of the transaction and network bandwidth, the
15 transfer time may significantly increase the apply lag.
17 To reduce the apply lag caused by large transactions, an output plugin
18 may provide additional callback to support incremental streaming of
19 in-progress transactions. There are multiple required streaming
20 callbacks (stream_start_cb, stream_stop_cb, stream_abort_cb,
21 stream_commit_cb and stream_change_cb) and two optional callbacks
22 (stream_message_cb and stream_truncate_cb). Also, if streaming of
23 two-phase commands is to be supported, then additional callbacks must
24 be provided. (See Section 47.10 for details).
26 When streaming an in-progress transaction, the changes (and messages)
27 are streamed in blocks demarcated by stream_start_cb and stream_stop_cb
28 callbacks. Once all the decoded changes are transmitted, the
29 transaction can be committed using the stream_commit_cb callback (or
30 possibly aborted using the stream_abort_cb callback). If two-phase
31 commits are supported, the transaction can be prepared using the
32 stream_prepare_cb callback, COMMIT PREPARED using the
33 commit_prepared_cb callback or aborted using the rollback_prepared_cb.
35 One example sequence of streaming callback calls for one transaction
37 stream_start_cb(...); <-- start of first block of changes
38 stream_change_cb(...);
39 stream_change_cb(...);
40 stream_message_cb(...);
41 stream_change_cb(...);
43 stream_change_cb(...);
44 stream_stop_cb(...); <-- end of first block of changes
46 stream_start_cb(...); <-- start of second block of changes
47 stream_change_cb(...);
48 stream_change_cb(...);
49 stream_change_cb(...);
51 stream_message_cb(...);
52 stream_change_cb(...);
53 stream_stop_cb(...); <-- end of second block of changes
56 [a. when using normal commit]
57 stream_commit_cb(...); <-- commit of the streamed transaction
59 [b. when using two-phase commit]
60 stream_prepare_cb(...); <-- prepare the streamed transaction
61 commit_prepared_cb(...); <-- commit of the prepared transaction
63 The actual sequence of callback calls may be more complicated, of
64 course. There may be blocks for multiple streamed transactions, some of
65 the transactions may get aborted, etc.
67 Similar to spill-to-disk behavior, streaming is triggered when the
68 total amount of changes decoded from the WAL (for all in-progress
69 transactions) exceeds the limit defined by logical_decoding_work_mem
70 setting. At that point, the largest top-level transaction (measured by
71 the amount of memory currently used for decoded changes) is selected
72 and streamed. However, in some cases we still have to spill to disk
73 even if streaming is enabled because we exceed the memory threshold but
74 still have not decoded the complete tuple e.g., only decoded toast
75 table insert but not the main table insert.
77 Even when streaming large transactions, the changes are still applied
78 in commit order, preserving the same guarantees as the non-streaming