From 6699534c03772b0e5b06680b2e382a36eb108a67 Mon Sep 17 00:00:00 2001 From: Jim Jones Date: Wed, 25 Mar 2026 23:14:12 +0100 Subject: [PATCH v3 1/2] Skip other sessions' temp tables in REPACK, CLUSTER, and VACUUM FULL get_tables_to_repack() was including other sessions' temporary tables in the work list, causing REPACK and CLUSTER (without arguments) to attempt to acquire AccessExclusiveLock on them, potentially blocking for an extended time. Fix by skipping other-session temp tables early in get_tables_to_repack(), before they are added to the list. Because an AccessShareLock has already been acquired per relation at that point, release it before continuing. Similarly, get_all_vacuum_rels() suffered from the same problem for VACUUM FULL. Since no per-relation lock is held during list-building there, a plain skip suffices. Author: Jim Jones Reviewed-by: Chao Li Reviewed-by: Zsolt Parragi --- src/backend/commands/cluster.c | 25 ++++++++++++++++++++++++- src/backend/commands/vacuum.c | 5 +++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index 09066db0956..14c11e8e532 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -1679,6 +1679,8 @@ get_tables_to_repack(RepackCommand cmd, bool usingindex, MemoryContext permcxt) { RelToCluster *rtc; Form_pg_index index; + HeapTuple classtup; + Form_pg_class classForm; MemoryContext oldcxt; index = (Form_pg_index) GETSTRUCT(tuple); @@ -1693,11 +1695,24 @@ get_tables_to_repack(RepackCommand cmd, bool usingindex, MemoryContext permcxt) continue; /* Verify that the table still exists; skip if not */ - if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(index->indrelid))) + classtup = SearchSysCache1(RELOID, ObjectIdGetDatum(index->indrelid)); + if (!HeapTupleIsValid(classtup)) { UnlockRelationOid(index->indrelid, AccessShareLock); continue; } + classForm = (Form_pg_class) GETSTRUCT(classtup); + + /* Skip temp relations belonging to other sessions */ + if (classForm->relpersistence == RELPERSISTENCE_TEMP && + !isTempOrTempToastNamespace(classForm->relnamespace)) + { + ReleaseSysCache(classtup); + UnlockRelationOid(index->indrelid, AccessShareLock); + continue; + } + + ReleaseSysCache(classtup); /* noisily skip rels which the user can't process */ if (!repack_is_permitted_for_relation(cmd, index->indrelid, @@ -1753,6 +1768,14 @@ get_tables_to_repack(RepackCommand cmd, bool usingindex, MemoryContext permcxt) continue; } + /* Skip temp relations belonging to other sessions */ + if (class->relpersistence == RELPERSISTENCE_TEMP && + !isTempOrTempToastNamespace(class->relnamespace)) + { + UnlockRelationOid(class->oid, AccessShareLock); + continue; + } + /* noisily skip rels which the user can't process */ if (!repack_is_permitted_for_relation(cmd, class->oid, GetUserId())) diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index bce3a2daa24..9b0a5a38a8a 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -1062,6 +1062,11 @@ get_all_vacuum_rels(MemoryContext vac_context, int options) classForm->relkind != RELKIND_PARTITIONED_TABLE) continue; + /* Skip temp relations belonging to other sessions */ + if (classForm->relpersistence == RELPERSISTENCE_TEMP && + !isTempOrTempToastNamespace(classForm->relnamespace)) + continue; + /* check permissions of relation */ if (!vacuum_is_permitted_for_relation(relid, classForm, options)) continue; -- 2.43.0