From 92caf8f7bb7e64e7b91cba089a17d7255ab94004 Mon Sep 17 00:00:00 2001 From: Ayush Tiwari Date: Mon, 28 Sep 2026 17:38:13 +0530 Subject: [PATCH v2 1/2] Recheck table sync state after refresh An apply worker can cache a table's SYNCDONE state and then wait for the subscription lock while ALTER SUBSCRIPTION ... REFRESH PUBLICATION removes that table. The worker then tries to mark the absent catalog row READY and errors out. With disable_on_error, that disables the entire subscription, including unrelated tables. Two refreshes can also remove and re-add the table before the apply worker gets the lock. Completing the old sync would then mark the new INIT row READY and skip its initial copy. Re-read the table state after taking the subscription lock, and skip the READY transition unless it is still SYNCDONE. This table-side issue predates the sequence-side fix in dca73f7dd03. --- src/backend/replication/logical/tablesync.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c index 4015e861a64..6c211ec0e62 100644 --- a/src/backend/replication/logical/tablesync.c +++ b/src/backend/replication/logical/tablesync.c @@ -433,9 +433,8 @@ ProcessSyncingTablesForApply(XLogRecPtr current_lsn) if (current_lsn >= rstate->lsn) { char originname[NAMEDATALEN]; - - rstate->state = SUBREL_STATE_READY; - rstate->lsn = current_lsn; + char current_relstate; + XLogRecPtr statelsn; /* * Remove the tablesync origin tracking if exists. @@ -455,6 +454,19 @@ ProcessSyncingTablesForApply(XLogRecPtr current_lsn) LockSharedObject(SubscriptionRelationId, MyLogicalRepWorker->subid, 0, AccessShareLock); + /* The table may have been removed or re-added meanwhile. */ + current_relstate = GetSubscriptionRelState(MyLogicalRepWorker->subid, + rstate->relid, &statelsn); + if (current_relstate != SUBREL_STATE_SYNCDONE) + { + elog(DEBUG1, "skipping READY transition for relation %u of subscription \"%s\" as it is no longer SYNCDONE", + rstate->relid, MySubscription->name); + continue; + } + + rstate->state = SUBREL_STATE_READY; + rstate->lsn = current_lsn; + if (!rel) rel = table_open(SubscriptionRelRelationId, RowExclusiveLock); -- 2.34.1