Author: Noah Misch Commit: Noah Misch Add relation locks where existing standards would have them. The SetRelationHasSubclass() header comment says to hold this ShareUpdateExclusiveLock lock, and it's conventional for the sort of DDL done there and in IndexSetParentIndex(). SequenceChangePersistence() and heap_create() are deep surgery warranting AccessExclusiveLock. This might cause more deadlocks. I didn't run down exact user-visible bugs reachable via these gaps. Back-patch to v12 (all supported versions). Reviewed by FIXME. Discussion: https://postgr.es/m/FIXME diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c index 922ba79..2652405 100644 --- a/src/backend/catalog/heap.c +++ b/src/backend/catalog/heap.c @@ -407,6 +407,8 @@ heap_create(const char *relname, /* ensure that stats are dropped if transaction aborts */ pgstat_create_relation(rel); + LockRelationOid(relid, AccessExclusiveLock); + return rel; } diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c index 5a8568c..5c48e57 100644 --- a/src/backend/catalog/index.c +++ b/src/backend/catalog/index.c @@ -1058,6 +1058,7 @@ index_create(Relation heapRelation, if (OidIsValid(parentIndexRelid)) { StoreSingleInheritance(indexRelationId, parentIndexRelid, 1); + LockRelationOid(parentIndexRelid, ShareUpdateExclusiveLock); SetRelationHasSubclass(parentIndexRelid, true); } diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index d9016ef..a28ce72 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -4475,7 +4475,10 @@ IndexSetParentIndex(Relation partitionIdx, Oid parentOid) /* set relhassubclass if an index partition has been added to the parent */ if (OidIsValid(parentOid)) + { + LockRelationOid(parentOid, ShareUpdateExclusiveLock); SetRelationHasSubclass(parentOid, true); + } /* set relispartition correctly on the partition */ update_relispartition(partRelid, OidIsValid(parentOid)); @@ -4527,6 +4530,7 @@ update_relispartition(Oid relationId, bool newval) HeapTuple tup; Relation classRel; + LockRelationOid(relationId, ShareUpdateExclusiveLock); classRel = table_open(RelationRelationId, RowExclusiveLock); tup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId)); if (!HeapTupleIsValid(tup)) diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index 4610356..a60d6e7 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -545,6 +545,7 @@ SequenceChangePersistence(Oid relid, char newrelpersistence) Buffer buf; HeapTupleData seqdatatuple; + LockRelationOid(relid, AccessExclusiveLock); init_sequence(relid, &elm, &seqrel); /* check the comment above nextval_internal()'s equivalent call. */