postgres.git / summary / log / commit / refs

commit    4778826532a62fd6e4d3fdeef9532c943604c730
Author:   Amit Kapila <akapila@postgresql.org>
Date:     Thu Apr 01 02:27:34 2021 +0000
First released in: 14.0

    Ensure to send a prepare after we detect concurrent abort during decoding.
    
    It is possible that while decoding a prepared transaction, it gets aborted
    concurrently via a ROLLBACK PREPARED command. In that case, we were
    skipping all the changes and directly sending Rollback Prepared when we
    find the same in WAL. However, the downstream has no idea of the GID of
    such a transaction. So, ensure to send prepare even when a concurrent
    abort is detected.
    
    Author: Ajin Cherian
    Reviewed-by: Markus Wanner, Amit Kapila
    Discussion: https://postgr.es/m/f82133c6-6055-b400-7922-97dae9f2b50b@enterprisedb.com


doc/src/sgml/logicaldecoding.sgml | 15 +++++++++------ src/backend/replication/logical/reorderbuffer.c | 8 ++++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/doc/src/sgml/logicaldecoding.sgml b/doc/src/sgml/logicaldecoding.sgml index da23f89ca32..5d049cdc687 100644 --- a/doc/src/sgml/logicaldecoding.sgml +++ b/doc/src/sgml/logicaldecoding.sgml @@ -545,12 +545,15 @@ CREATE TABLE another_catalog_table(data text) WITH (user_catalog_table = true); executed within that transaction. A transaction that is prepared for a two-phase commit using <command>PREPARE TRANSACTION</command> will also be decoded if the output plugin callbacks needed for decoding - them are provided. It is possible that the current transaction which - is being decoded is aborted concurrently via a <command>ROLLBACK PREPARED</command> - command. In that case, the logical decoding of this transaction will - be aborted too. We will skip all the changes of such a transaction once - the abort is detected and abort the transaction when we read WAL for - <command>ROLLBACK PREPARED</command>. + them are provided. It is possible that the current prepared transaction + which is being decoded is aborted concurrently via a + <command>ROLLBACK PREPARED</command> command. In that case, the logical + decoding of this transaction will be aborted too. All the changes of such + a transaction are skipped once the abort is detected and the + <function>prepare_cb</function> callback is invoked. Thus even in case of + a concurrent abort, enough information is provided to the output plugin + for it to properly deal with <command>ROLLBACK PREPARED</command> once + that is decoded. </para> <note> diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c index 127f2c4b168..52d06285a21 100644 --- a/src/backend/replication/logical/reorderbuffer.c +++ b/src/backend/replication/logical/reorderbuffer.c @@ -2664,6 +2664,14 @@ ReorderBufferPrepare(ReorderBuffer *rb, TransactionId xid, ReorderBufferReplay(txn, rb, xid, txn->final_lsn, txn->end_lsn, txn->commit_time, txn->origin_id, txn->origin_lsn); + + /* + * We send the prepare for the concurrently aborted xacts so that later + * when rollback prepared is decoded and sent, the downstream should be + * able to rollback such a xact. See comments atop DecodePrepare. + */ + if (txn->concurrent_abort) + rb->prepare(rb, txn, txn->final_lsn); } /* [parent: 0d1a33438d3a]