From a52d72efa325edceb6928e5e84a404d51a4e32eb Mon Sep 17 00:00:00 2001 From: Zhijie Hou Date: Fri, 13 Nov 2026 09:58:46 +0800 Subject: [PATCH v1] Document prepared transaction lock waits with two_phase subscriptions. When two_phase is enabled for a subscription, a transaction prepared by the apply worker continues to hold its locks until COMMIT PREPARED or ROLLBACK PREPARED is applied. If another session requests a conflicting lock on a table modified by that prepared transaction, it waits behind the prepared transaction, and subsequent lock requests by the apply worker on the same table queue behind that session. Because the prepared transaction is not waiting on any lock, this wait cycle is not detected as a deadlock and replication stalls. Document this caveat and how to recover from it under CREATE SUBSCRIPTION and PREPARE TRANSACTION. --- doc/src/sgml/ref/create_subscription.sgml | 21 +++++++++++++++++++++ doc/src/sgml/ref/prepare_transaction.sgml | 5 ++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/doc/src/sgml/ref/create_subscription.sgml b/doc/src/sgml/ref/create_subscription.sgml index 6248c228a64..b2e6b8d9360 100644 --- a/doc/src/sgml/ref/create_subscription.sgml +++ b/doc/src/sgml/ref/create_subscription.sgml @@ -424,6 +424,27 @@ CREATE SUBSCRIPTION subscription_name + + A prepared transaction applied on the subscriber keeps its locks + until the apply worker processes the corresponding + COMMIT PREPARED or ROLLBACK + PREPARED. If another session requests a conflicting lock + on a table modified by such a transaction (for example, with + LOCK, TRUNCATE, or + ALTER TABLE), it has to wait, and later lock + requests on that table, including the apply worker's own next + change to it, queue behind it. The apply worker then cannot reach + the COMMIT PREPARED or ROLLBACK + PREPARED that would release the lock, and the sessions + wait for each other. This is not detected as a deadlock, so + replication stalls. To resolve this, either cancel the waiting + session, or manually roll back the prepared transaction on the + subscriber, disable two_phase (see + ALTER SUBSCRIPTION ... SET) + until that transaction is committed on the publisher and replicated + again, and then re-enable two_phase if required. + + The implementation of two-phase commit requires that replication has successfully finished the initial table synchronization diff --git a/doc/src/sgml/ref/prepare_transaction.sgml b/doc/src/sgml/ref/prepare_transaction.sgml index f4f6118ac31..22f4feca64d 100644 --- a/doc/src/sgml/ref/prepare_transaction.sgml +++ b/doc/src/sgml/ref/prepare_transaction.sgml @@ -132,7 +132,10 @@ PREPARE TRANSACTION transaction_id continues to hold whatever locks it held. The intended usage of the feature is that a prepared transaction will normally be committed or rolled back as soon as an external transaction manager has verified that - other databases are also prepared to commit. + other databases are also prepared to commit. A transaction prepared by a + logical replication apply worker can be completed only by that worker, see + for a + lock wait this can cause. -- 2.54.0 (Apple Git-157)