From 9ee74d0b07aa81204ba3adcfa1404ba9dccd6cd3 Mon Sep 17 00:00:00 2001 From: Shayon Mukherjee Date: Tue, 7 Oct 2025 12:43:30 -0400 Subject: [PATCH v1] Allow reads to proceed during FK/trigger drops by reducing relation-level lock from AccessExclusive to ShareRowExclusive --- src/backend/catalog/pg_constraint.c | 7 ++++--- src/backend/commands/tablecmds.c | 6 +++--- src/backend/commands/trigger.c | 6 ++++-- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c index 6002fd0002..13b21b6ee1 100644 --- a/src/backend/catalog/pg_constraint.c +++ b/src/backend/catalog/pg_constraint.c @@ -913,10 +913,11 @@ RemoveConstraintById(Oid conId) Relation rel; /* - * If the constraint is for a relation, open and exclusive-lock the - * relation it's for. + * If the constraint is for a relation, open and lock the relation. + * ShareRowExclusiveLock allows readers to proceed while blocking + * concurrent writers during constraint removal. */ - rel = table_open(con->conrelid, AccessExclusiveLock); + rel = table_open(con->conrelid, ShareRowExclusiveLock); /* * We need to update the relchecks count if it is a check constraint diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index fc89352b66..d2f73b9c34 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -15474,11 +15474,11 @@ ATPostAlterTypeCleanup(List **wqueue, AlteredTableInfo *tab, LOCKMODE lockmode) /* * When rebuilding another table's constraint that references the * table we're modifying, we might not yet have any lock on the other - * table, so get one now. We'll need AccessExclusiveLock for the DROP - * CONSTRAINT step, so there's no value in asking for anything weaker. + * table, so get one now. Use ShareRowExclusiveLock to block writers + * but allow readers during the DROP CONSTRAINT step. */ if (relid != tab->relid) - LockRelationOid(relid, AccessExclusiveLock); + LockRelationOid(relid, ShareRowExclusiveLock); ATPostAlterTypeParse(oldId, relid, confrelid, (char *) lfirst(def_item), diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 579ac8d76a..fae0cc9a92 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -1315,11 +1315,13 @@ RemoveTriggerById(Oid trigOid) elog(ERROR, "could not find tuple for trigger %u", trigOid); /* - * Open and exclusive-lock the relation the trigger belongs to. + * Open and lock the relation the trigger belongs to. + * ShareRowExclusiveLock allows reads while blocking concurrent writes + * during trigger removal. */ relid = ((Form_pg_trigger) GETSTRUCT(tup))->tgrelid; - rel = table_open(relid, AccessExclusiveLock); + rel = table_open(relid, ShareRowExclusiveLock); if (rel->rd_rel->relkind != RELKIND_RELATION && rel->rd_rel->relkind != RELKIND_VIEW && -- 2.39.5 (Apple Git-154)