| From: | Amit Kapila <akapila(at)postgresql(dot)org> |
|---|---|
| To: | pgsql-committers(at)lists(dot)postgresql(dot)org |
| Subject: | pgsql: Avoid resetting subscription two_phase state to pending when alr |
| Date: | 2026-11-05 04:25:46 |
| Message-ID: | E1xOp2p-00000000G71-0ren@gemulon.postgresql.org |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-committers |
Avoid resetting subscription two_phase state to pending when already enabled.
ALTER SUBSCRIPTION ... SET (two_phase = true) always moved the
subscription's two_phase state to pending, even if two_phase was already
enabled. The publisher's slot still has two_phase enabled in that case,
and prepared transactions may already exist on the subscriber, so the
reset broke checks that rely on the enabled state:
1. A later SET (two_phase = false) no longer checked for existing prepared
transactions and disabled two_phase anyway. When those transactions were
committed on the publisher, their changes were re-sent as regular
transactions instead of COMMIT PREPARED, leading to self-deadlocks,
duplicate data, or orphaned prepared transactions.
2. REFRESH PUBLICATION (and SET/ADD PUBLICATION) with copy_data = true was
allowed even though the publisher's slot still had two_phase enabled. This
could stream prepared transactions during the initial sync of newly added
tables and apply them as empty prepares.
Fix this by leaving the state unchanged when two_phase is already enabled.
This problem was introduced by commit 1462aad2e44, which allowed altering
the two_phase option of a subscription.
This changes behavior when slot_name is altered together with SET
(two_phase = true) on an ENABLED subscription. Previously the state was
reset to PENDING and the apply worker enabled two_phase on the replacement
slot. Now the state stays ENABLED and the apply worker does not touch the
replacement slot's two_phase property. This is intentional: resetting the
state would reintroduce the problems described above, since prepared
transactions from the old slot may still exist on the subscriber. The
documentation already requires the replacement slot's two_phase property
to match the subscription option.
Author: Zhijie Hou <houzhijie22(at)gmail(dot)com>
Reviewed-by: shveta malik <shveta(dot)malik(at)gmail(dot)com>
Reviewed-by: Hayato Kuroda <kuroda(dot)hayato(at)fujitsu(dot)com>
Reviewed-by: Bertrand Drouvot <bertranddrouvot(dot)pg(at)gmail(dot)com>
Reviewed-by: vignesh C <vignesh21(at)gmail(dot)com>
Reviewed-by: Peter Smith <smithpb2250(at)gmail(dot)com>
Reviewed-by: Amit Kapila <amit(dot)kapila16(at)gmail(dot)com>
Discussion: https://postgr.es/m/8e85abdf-738b-4578-ac42-4dc8eaa061dd@gmail.com
Backpatch-through: 18
Branch
------
REL_19_STABLE
Details
-------
https://git.postgresql.org/pg/commitdiff/1e1a4821a9efefe4a813932d1510c6704938f713
Modified Files
--------------
src/backend/commands/subscriptioncmds.c | 19 +++++++++++++------
src/test/subscription/t/021_twophase.pl | 16 +++++++++++++---
2 files changed, 26 insertions(+), 9 deletions(-)
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Amit Langote | 2026-11-05 07:31:27 | pgsql: SQL/JSON: Fix NULL result leakage in JSON_VALUE() RETURNING json |
| Previous Message | Michael Paquier | 2026-11-05 00:14:01 | pgsql: Add stats kind filter to pgstat_drop_matching_entries() |