From df748108d10f3435410a524fc12ad6c7d06b4659 Mon Sep 17 00:00:00 2001 From: Vignesh C Date: Sat, 11 Jul 2026 12:02:17 +0530 Subject: [PATCH 1/2] Reject concurrent sequence refreshes `ALTER SUBSCRIPTION ... REFRESH SEQUENCES` can race with an already running sequence synchronization worker. If a second refresh request resets the synchronization state while the worker has already fetched sequence values from the publisher but has not yet applied them to the subscriber, the worker can overwrite the subscriber with stale values and mark the synchronization as complete. Avoid this race by rejecting `ALTER SUBSCRIPTION ... REFRESH SEQUENCES` when a sequence synchronization worker is already running for the subscription. The command reports an error asking the user to rerun it after the current synchronization completes. --- src/backend/commands/subscriptioncmds.c | 23 +++++++++++++++++++++++ src/test/subscription/t/036_sequences.pl | 4 ++++ 2 files changed, 27 insertions(+) diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c index 4292e7fb8f4..1a1c550cc14 100644 --- a/src/backend/commands/subscriptioncmds.c +++ b/src/backend/commands/subscriptioncmds.c @@ -1363,6 +1363,29 @@ AlterSubscription_refresh_seq(Subscription *sub) WalReceiverConn *wrconn; bool must_use_password; + /* + * Disallow a concurrent REFRESH SEQUENCES while a sequencesync worker + * for this subscription is still synchronizing the sequences from a + * previous REFRESH SEQUENCES. Without this check, this command would + * reset the sequences' state back to INIT while the running worker is + * midway through applying the values it already fetched from the + * publisher, which could leave the sequences marked READY with stale + * data. + */ + LWLockAcquire(LogicalRepWorkerLock, LW_SHARED); + if (logicalrep_worker_find(WORKERTYPE_SEQUENCESYNC, sub->oid, InvalidOid, + true)) + { + LWLockRelease(LogicalRepWorkerLock); + ereport(ERROR, + errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("cannot execute %s while a sequence synchronization worker for subscription \"%s\" is still running", + "ALTER SUBSCRIPTION ... REFRESH SEQUENCES", + sub->name), + errhint("Try again after the current synchronization completes.")); + } + LWLockRelease(LogicalRepWorkerLock); + /* Load the library providing us libpq calls. */ load_file("libpqwalreceiver", false); diff --git a/src/test/subscription/t/036_sequences.pl b/src/test/subscription/t/036_sequences.pl index 2a0819aaf01..8b02b24a7e9 100644 --- a/src/test/subscription/t/036_sequences.pl +++ b/src/test/subscription/t/036_sequences.pl @@ -232,6 +232,10 @@ $node_publisher->safe_psql( CREATE SEQUENCE regress_s4 START 10 INCREMENT 2; )); +# Wait for the missing sequence added to be synced +$node_subscriber->poll_query_until('postgres', $synced_query) + or die "Timed out while waiting for subscriber to synchronize data"; + ########## # Ensure that insufficient privileges on the publisher for a sequence # are reported correctly as a permission issue, not as a missing sequence. -- 2.50.1 (Apple Git-155)