]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Skip other sessions' temp tables in REPACK, CLUSTER, and VACUUM FULL
authorÁlvaro Herrera <alvherre@kurilemu.de>
Tue, 5 May 2026 14:20:26 +0000 (16:20 +0200)
committerÁlvaro Herrera <alvherre@kurilemu.de>
Tue, 5 May 2026 14:20:26 +0000 (16:20 +0200)
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 <jim.jones@uni-muenster.de>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com>
Discussion: https://postgr.es/m/0b555318-2bf2-46df-9377-09629a2a59db@uni-muenster.de

src/backend/commands/repack.c
src/backend/commands/vacuum.c

index dca3997c31b3dc5f827c667ff0e1818221662779..9a199dd9bfbfcbfdbfc19ae7a3c1f2ef49d7befc 100644 (file)
@@ -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()))
index 99d0db82ed7f48d3eb930d3915108bb70bbc2f24..a4abb29cf64ef2806d892b618a5d144fea65a2e5 100644 (file)
@@ -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;