Базовые функции обратного вызова плагина вывода (например,
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
).
Кроме того, если необходимо обеспечить поддержку потоковой передачи двухфазных команд, следует реализовать дополнительные
функции обратного вызова. (См.
Раздел 5.12.10
для получения подробных сведений).
При потоковой передаче выполняющейся транзакции изменения (и сообщения) передаются блоками, разграниченными вызовами
stream_start_cb
и
stream_stop_cb
функций обратного вызова. После передачи всех декодированных
изменений транзакция может быть зафиксирована с помощью функции обратного вызова
stream_commit_cb
функции обратного вызова (или, возможно, прервана с помощью
stream_abort_cb
).
Если поддерживаются двухфазные фиксации, транзакция может быть подготовлена с помощью функции обратного вызова
stream_prepare_cb
callback,
COMMIT PREPARED
с помощью функции обратного вызова
commit_prepared_cb
или прервана с помощью функции обратного вызова
rollback_prepared_cb
.
Пример последовательности вызовов функций обратного вызова потоковой передачи для одной транзакции может выглядеть следующим образом:
stream_start_cb(...); <-- начало первого блока изменений stream_change_cb(...); stream_change_cb(...); stream_message_cb(...); stream_change_cb(...); ... stream_change_cb(...); stream_stop_cb(...); <-- конец первого блока изменений stream_start_cb(...); <-- начало второго блока изменений stream_change_cb(...); stream_change_cb(...); stream_change_cb(...); ... stream_message_cb(...); stream_change_cb(...); stream_stop_cb(...); <-- конец второго блока изменений [a. при использовании обычной фиксации] stream_commit_cb(...); <-- фиксация потоковой транзакции [b. при использовании двухфазной фиксации] stream_prepare_cb(...); <-- подготовка потоковой транзакции commit_prepared_cb(...); <-- фиксация подготовленной транзакции
Разумеется, фактическая последовательность вызовов функций обратного вызова может быть более сложной. Могут присутствовать блоки для нескольких потоковых транзакций, некоторые транзакции могут быть отменены и т. д.
По аналогии со сбросом данных на диск, потоковая передача инициируется, когда общий объем изменений, декодированных из WAL (для всех транзакций в процессе выполнения), превышает лимит, установленный параметром
logical_decoding_work_mem
параметра. В этот момент выбирается и передается в потоке самая большая транзакция верхнего уровня (оцениваемая по объему памяти, используемому в данный момент для декодированных изменений). Однако в ряде случаев сброс на диск необходим даже при включенной потоковой передаче, если порог памяти превышен, но кортеж еще не декодирован полностью (например, декодирована вставка в таблицу TOAST, но не в основную таблицу).
Даже при потоковой передаче больших транзакций изменения применяются в порядке их фиксации, что обеспечивает те же гарантии, что и в режиме без потоковой передачи.