Bug report and fix for: COMMIT/ROLLBACK AND CHAIN after an error drops the isolation level

From: Narek Galstyan <narek(dot)galstyan(at)enterprisedb(dot)com>
To: pgsql-hackers(at)postgresql(dot)org
Subject: Bug report and fix for: COMMIT/ROLLBACK AND CHAIN after an error drops the isolation level
Date: 2026-11-06 03:40:40
Message-ID: CAHsn6_z-ewqXWe2h--SK93AdnPSOvjvF9KLodWckFZKAjxcONw@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi all,

If a transaction block fails outside a savepoint,
the transaction started by COMMIT/ROLLBACK AND CHAIN
gets the default characteristics instead of the block's set characteristics:

START TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ ONLY,
DEFERRABLE;
SELECT 1/0; -- ERROR: division by zero
COMMIT AND CHAIN;
SHOW transaction_isolation; -- read committed, expected repeatable
read
SHOW transaction_read_only; -- off, expected on
SHOW transaction_deferrable; -- off, expected on
ROLLBACK;

START TRANSACTION;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ ONLY, DEFERRABLE;
SELECT 1/0; -- ERROR: division by zero
ROLLBACK AND CHAIN;
SHOW transaction_isolation; -- read committed, expected serializable
SHOW transaction_read_only; -- off, expected on
SHOW transaction_deferrable; -- off, expected on
ROLLBACK;

In the attached patchset, the first commit adds a regression test similar
to the above.

The second commit fixes AbortCurrentTransactionInternal to
keep the characteristics of a failed transaction block for AND CHAIN.

Details on the fix:

COMMIT AND CHAIN and ROLLBACK AND CHAIN start the new transaction with
the characteristics of the finished one, which
CommitTransactionCommand() reads when the command arrives.

AbortTransaction() reverts the isolation level, read-only and deferrable
settings set by BEGIN or SET TRANSACTION, along with the other GUCs. A
retry loop doing ROLLBACK AND CHAIN after a serialization failure thus
silently retried in READ COMMITTED.

The commit restores the characteristics right after AbortTransaction()
when a transaction block fails, so they last until the block ends. A
failed transaction that was itself started by AND CHAIN already keeps
them, because they are not set through the GUC stack.

Bug present since AND CHAIN was added in v12.

Attachment Content-Type Size
0002-Keep-the-characteristics-of-a-failed-transaction-blo.patch application/octet-stream 1.9 KB
0001-Add-tests-for-AND-CHAIN-after-an-error-in-a-non-chai.patch application/octet-stream 3.7 KB

Browse pgsql-hackers by date

  From Date Subject
Next Message Zhijie Hou 2026-11-06 04:13:11 Re: Avoid using raw xmin of frozen tuples in logicalrep conflict detection
Previous Message shveta malik 2026-11-06 03:37:54 Re: pg_dump --exclude-table loses FOR ALL TABLES EXCEPT publications