Les fonctions callbacks simples pour le plugin de sortie
(soit begin_cb
, change_cb
,
commit_cb
et message_cb
) sont
uniquement appelées quand la transaction se termine avec un COMMIT. Les
changements sont toujours décodés à partir des journaux de transactions,
mais sont seulement passés au plugin de sortie à la validation de la
transaction (et ignorés si la transaction est annulée).
Ceci signifie que, bien que le décodage survient de façon incrémental et pourrait déborder sur disque pour que l'utilisation de la mémoire reste sous contrôle, tous les changements décodés seront transmis au moment de la validation de la transaction (ou plus précisément quand le COMMIT sera décodé du journal de transaction). Suivant la taille de la transaction et la bande passante du réseau, le temps de transfert pourrait augmenter de façon significative le délai du rejeu.
Pour réduire le délai de rejeu causé par les grosses transactions, un
plugin de sortie peut fournir des fonctions callback supplémentaires pour
accepter un flux incrémental de transactions en cours. Il existe plusieurs
fonctions callback requises pour un flux
(stream_start_cb
,
stream_stop_cb
, stream_abort_cb
,
stream_commit_cb
et
stream_change_cb
) et deux fonctions callback
optionnelles (stream_message_cb
et
stream_truncate_cb
).
Lors du flux d'une transaction en cours, les changements (et les messages)
sont envoyés en blocs démarqués par les fonctions
stream_start_cb
et
stream_stop_cb
. Une fois que tous les changements
décodés ont été transmis, la transaction peut être validée en utilisant la
fonction callback stream_commit_cb
(ou possiblement
annulée en utilisant la fonction callback
stream_abort_cb
). Si les validations en deux phases
sont supportées, la transaction peut être préparée en utilisant la
fonction callback stream_prepare_cb
, la commande de
validation COMMIT PREPARED
en utilisant la fonction
callback commit_prepared_cb
, et la commande
d'annulation en utilisant la fonction callback
rollback_prepared_cb
.
Une séquence d'exemple d'appels de callbacks pour un flux sur une transaction pourrait ressembler à ceci :
stream_start_cb(...); <-- début du premier bloc de changements stream_change_cb(...); stream_change_cb(...); stream_message_cb(...); stream_change_cb(...); ... stream_change_cb(...); stream_stop_cb(...); <-- fin du premier bloc de changements stream_start_cb(...); <-- début du deuxième bloc de changements stream_change_cb(...); stream_change_cb(...); stream_change_cb(...); ... stream_message_cb(...); stream_change_cb(...); stream_stop_cb(...); <-- fin du deuxième bloc de changements [a. when using normal commit] stream_commit_cb(...); <-- validation de la transaction en flux [b. when using two-phase commit] stream_prepare_cb(...); <-- prépare la transaction en flux commit_prepared_cb(...); <-- commit de la transaction préparée
La séquence réelle d'appels de fonctions callback pourrait être plus compliquée bien sûr. Il pourrait y avoir des blocs pour plusieurs transactions en flux, certaines des transactions pourraient être annulées, etc.
De façon similaire au comportement de débordement sur disque, le flux est
déclenché quand la quantité totale de changements décodés du WAL
(pour toutes les transactions en cours) dépasse la limite définie par le
paramètre logical_decoding_work_mem
. À ce moment-là, la
transaction de haut niveau la plus large (mesuré par la quantité de
mémoire actuellement utilisée pour les changements décodés) est
sélectionnée et envoyée en flux. Néanmoins, dans certains cas, nous avons
encore besoin de déborder sur disque même si le flux est activé parce que
nous dépassons la limite de mémoire, mais nous n'avons pas encore décodé
la ligne complète, par exemple seulement le décodage de l'insertion d'un
TOAST, mais pas celle de la table principale.
Même lors de flux de grosses transactions, les changements sont toujours appliqués dans l'ordre des validations, préservant les mêmes garanties que le mode sans flux.