From a0a0c0c20ec5f8787bb1be5f476c4e59f6810634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro=20Herrera?= Date: Tue, 5 May 2026 16:20:26 +0200 Subject: [PATCH] Skip other sessions' temp tables in REPACK, CLUSTER, and VACUUM FULL get_tables_to_repack() and get_all_vacuum_rels() were including other sessions' temporary tables in their output work list, causing REPACK, CLUSTER and VACUUM FULL (when executed without a table list) to attempt to acquire AccessExclusiveLock on them, potentially blocking for an extended time. Fix by skipping other-session temp tables early, before they are added to the list. This issue is ancient, but there have been no complaints about it that I know of, so I'm opting for not backpatching at present. Author: Jim Jones Reviewed-by: Chao Li Reviewed-by: Zsolt Parragi Discussion: https://postgr.es/m/0b555318-2bf2-46df-9377-09629a2a59db@uni-muenster.de --- src/backend/commands/repack.c | 25 ++++++++++++++++++++++++- src/backend/commands/vacuum.c | 5 +++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c index dca3997c31b..9a199dd9bfb 100644 --- a/src/backend/commands/repack.c +++ b/src/backend/commands/repack.c @@ -2106,6 +2106,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); @@ -2120,11 +2122,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, @@ -2180,6 +2195,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 99d0db82ed7..a4abb29cf64 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -1063,6 +1063,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;