From 3beebde4991a6f00bd5c87978b2403c217143d10 Mon Sep 17 00:00:00 2001
From: Vignesh C <vignesh21@gmail.com>
Date: Mon, 27 Jul 2026 17:01:10 +0530
Subject: [PATCH v1 1/2] Avoid accumulating relation locks during sequence
 synchronization

The sequence synchronization worker acquired a RowExclusiveLock on every
INIT sequence while scanning pg_subscription_rel and retained those locks
until the transaction committed.

On subscriptions with many INIT sequences, this could exhaust the shared
lock table, causing the worker to repeatedly fail with "out of shared
memory".

The worker only needs to ensure that the sequence's identity (namespace
and name) remains stable while it is being synchronized. An
AccessShareLock is sufficient to prevent concurrent DROP, RENAME, and
SET SCHEMA operations from changing that identity.

Acquire an AccessShareLock instead and release it immediately after the
sequence has been synchronized. This avoids accumulating relation locks
while preserving the required protection against concurrent DDL.
---
 src/backend/replication/logical/sequencesync.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/src/backend/replication/logical/sequencesync.c b/src/backend/replication/logical/sequencesync.c
index fe506a98c20..72519e651fb 100644
--- a/src/backend/replication/logical/sequencesync.c
+++ b/src/backend/replication/logical/sequencesync.c
@@ -752,7 +752,13 @@ LogicalRepSyncSequences(void)
 
 		subrel = (Form_pg_subscription_rel) GETSTRUCT(tup);
 
-		sequence_rel = try_table_open(subrel->srrelid, RowExclusiveLock);
+		/*
+		 * Lock the sequence so its identity (namespace and name) cannot change
+		 * under us via a concurrent DROP, RENAME or SET SCHEMA. Release it
+		 * right away rather than at transaction end, to avoid accumulating a
+		 * lock per sequence.
+		 */
+		sequence_rel = try_table_open(subrel->srrelid, AccessShareLock);
 
 		/* Skip if sequence was dropped concurrently */
 		if (!sequence_rel)
@@ -761,7 +767,7 @@ LogicalRepSyncSequences(void)
 		/* Skip if the relation is not a sequence */
 		if (sequence_rel->rd_rel->relkind != RELKIND_SEQUENCE)
 		{
-			table_close(sequence_rel, NoLock);
+			table_close(sequence_rel, AccessShareLock);
 			continue;
 		}
 
@@ -779,7 +785,7 @@ LogicalRepSyncSequences(void)
 
 		MemoryContextSwitchTo(oldctx);
 
-		table_close(sequence_rel, NoLock);
+		table_close(sequence_rel, AccessShareLock);
 	}
 
 	/* Cleanup */
-- 
2.50.1 (Apple Git-155)

