From a1c3d9a2706c03790debbf7acd1ba70dcaa254ae Mon Sep 17 00:00:00 2001 From: Ajin Cherian Date: Tue, 8 Jul 2025 06:18:23 -0400 Subject: [PATCH] Fix a deadlock during ALTER SUBSCRIPTION ... DROP PUBLICATION When user drops a publication from a subscription, this will result in a publication refresh on the subscriber which will try and drop any pending origins. Meanwhile the apply worker could also be trying to cleanup origins. There could be a deadlock if the order of locking of SubscriptionRelRelationId and ReplicationOriginRelationId are inverted between the process_syncing_tables_for_apply() and AlterSubscription_refresh(). The fix is to get an AccessExclusiveLock on SubscriptionRelRelationId in process_syncing_tables_for_apply() in advance. --- src/backend/replication/logical/tablesync.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c index e6159ac..b2f9bad 100644 --- a/src/backend/replication/logical/tablesync.c +++ b/src/backend/replication/logical/tablesync.c @@ -379,6 +379,7 @@ process_syncing_tables_for_apply(XLogRecPtr current_lsn) static HTAB *last_start_times = NULL; ListCell *lc; bool started_tx = false; + Relation rel = NULL; Assert(!IsTransactionState()); @@ -470,7 +471,14 @@ process_syncing_tables_for_apply(XLogRecPtr current_lsn) * refresh for the subscription where we remove the table * state and its origin and by this time the origin might be * already removed. So passing missing_ok = true. + * + * Also Lock pg_subscription_rel with AccessExclusiveLock to + * prevent any deadlocks with user concurrently performing + * refresh on the subscription. */ + + rel = table_open(SubscriptionRelRelationId, AccessExclusiveLock); + ReplicationOriginNameForTablesync(MyLogicalRepWorker->subid, rstate->relid, originname, @@ -483,6 +491,9 @@ process_syncing_tables_for_apply(XLogRecPtr current_lsn) UpdateSubscriptionRelState(MyLogicalRepWorker->subid, rstate->relid, rstate->state, rstate->lsn); + + /* close and unlock table */ + table_close(rel, AccessExclusiveLock); } } else -- 1.8.3.1