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 <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
master
Álvaro Herrera 2 days ago
parent 6766264262
commit a0a0c0c20e
No known key found for this signature in database
GPG Key ID: 1C20ACB9D5C564AE
  1. 25
      src/backend/commands/repack.c
  2. 5
      src/backend/commands/vacuum.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()))

@ -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;

Loading…
Cancel
Save