From dd642a2293e09ae1b559c1b73a053f3fd33bc68f Mon Sep 17 00:00:00 2001 From: Vaijayanti Bharadwaj Date: Tue, 27 Oct 2026 22:07:22 +0530 Subject: [PATCH v2 1/2] Fix concurrent-abort detection for subtransactions of prepared xacts When decoding a prepared transaction at PREPARE time, ReorderBufferProcessTXN() is supposed to set CheckXidAlive for each change, so that a catalog scan notices if the transaction is rolled back concurrently. The condition tested rbtxn_is_prepared() on the change's own ReorderBufferTXN, but RBTXN_IS_PREPARED is only set on the top-level transaction. Changes made in the first subtransaction therefore never set CheckXidAlive. If such a transaction made a catalog change and then DML inside a subtransaction, and was rolled back with ROLLBACK PREPARED while being decoded, the decoder could go on using catalog tuples whose xmax had been overwritten by a later transaction, and decode the DML with the wrong catalog version. Fix is to test the flag on the top-level transaction instead. CheckXidAlive is still set to the subtransaction's xid, which aborts together with its parent once the transaction is prepared. Backpatch-through: 14 --- src/backend/replication/logical/reorderbuffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c index 6c4eadc9972..b8b3efed946 100644 --- a/src/backend/replication/logical/reorderbuffer.c +++ b/src/backend/replication/logical/reorderbuffer.c @@ -2305,7 +2305,7 @@ ReorderBufferProcessTXN(ReorderBuffer *rb, ReorderBufferTXN *txn, * required for the cases when we decode the changes before the * COMMIT record is processed. */ - if (streaming || rbtxn_is_prepared(change->txn)) + if (streaming || rbtxn_is_prepared(txn)) { curtxn = change->txn; SetupCheckXidLive(curtxn->xid); -- 2.55.0