From 81f01e3cc649bd752944524dddc9382b90d8d0a5 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Thu, 5 Apr 2018 19:04:25 +0000 Subject: [PATCH v7 11/12] Skip VACUUM FULL with VACOPT_SKIP_LOCKED if cluster_rel() would block. --- src/backend/commands/cluster.c | 37 +++++++++++++++++++++++++------------ src/backend/commands/vacuum.c | 5 +++-- src/include/commands/cluster.h | 4 ++-- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index d088dc11a6..63486bf34f 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -186,7 +186,7 @@ cluster(ClusterStmt *stmt, bool isTopLevel) heap_close(rel, NoLock); /* Do the job. */ - cluster_rel(tableOid, indexOid, false, stmt->verbose); + cluster_rel(tableOid, indexOid, false, stmt->verbose, false); } else { @@ -234,7 +234,7 @@ cluster(ClusterStmt *stmt, bool isTopLevel) /* functions in indexes may want a snapshot set */ PushActiveSnapshot(GetTransactionSnapshot()); /* Do the job. */ - cluster_rel(rvtc->tableOid, rvtc->indexOid, true, stmt->verbose); + cluster_rel(rvtc->tableOid, rvtc->indexOid, true, stmt->verbose, false); PopActiveSnapshot(); CommitTransactionCommand(); } @@ -263,9 +263,15 @@ cluster(ClusterStmt *stmt, bool isTopLevel) * If indexOid is InvalidOid, the table will be rewritten in physical order * instead of index order. This is the new implementation of VACUUM FULL, * and error messages should refer to the operation as VACUUM not CLUSTER. + * + * If skip_locked is true and the relation cannot be immediately locked, + * processing will be skipped and false will be returned (otherwise, true is + * returned). Note that skip_locked will not prevent blocking on the index + * provided. Since this functionality is only used for VACUUM FULL, this + * omission has no effect. */ -void -cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose) +bool +cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose, bool skip_locked) { Relation OldHeap; @@ -278,11 +284,16 @@ cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose) * case, since cluster() already did it.) The index lock is taken inside * check_index_is_clusterable. */ - OldHeap = try_relation_open(tableOid, AccessExclusiveLock); + if (!skip_locked) + OldHeap = try_relation_open(tableOid, AccessExclusiveLock); + else if (ConditionalLockRelationOid(tableOid, AccessExclusiveLock)) + OldHeap = try_relation_open(tableOid, NoLock); + else + return false; /* If the table has gone away, we can skip processing it */ if (!OldHeap) - return; + return true; /* * Since we may open a new transaction for each relation, we have to check @@ -301,7 +312,7 @@ cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose) if (!pg_class_ownercheck(tableOid, GetUserId())) { relation_close(OldHeap, AccessExclusiveLock); - return; + return true; } /* @@ -315,7 +326,7 @@ cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose) if (RELATION_IS_OTHER_TEMP(OldHeap)) { relation_close(OldHeap, AccessExclusiveLock); - return; + return true; } if (OidIsValid(indexOid)) @@ -326,7 +337,7 @@ cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose) if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(indexOid))) { relation_close(OldHeap, AccessExclusiveLock); - return; + return true; } /* @@ -336,14 +347,14 @@ cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose) if (!HeapTupleIsValid(tuple)) /* probably can't happen */ { relation_close(OldHeap, AccessExclusiveLock); - return; + return true; } indexForm = (Form_pg_index) GETSTRUCT(tuple); if (!indexForm->indisclustered) { ReleaseSysCache(tuple); relation_close(OldHeap, AccessExclusiveLock); - return; + return true; } ReleaseSysCache(tuple); } @@ -397,7 +408,7 @@ cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose) !RelationIsPopulated(OldHeap)) { relation_close(OldHeap, AccessExclusiveLock); - return; + return true; } /* @@ -412,6 +423,8 @@ cluster_rel(Oid tableOid, Oid indexOid, bool recheck, bool verbose) rebuild_relation(OldHeap, indexOid, verbose); /* NB: rebuild_relation does heap_close() on OldHeap */ + + return true; } /* diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index f19d112af6..74349f30d9 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -1558,8 +1558,9 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params) onerel = NULL; /* VACUUM FULL is now a variant of CLUSTER; see cluster.c */ - cluster_rel(relid, InvalidOid, false, - (options & VACOPT_VERBOSE) != 0); + skipped = !cluster_rel(relid, InvalidOid, false, + (options & VACOPT_VERBOSE) != 0, + (options & VACOPT_SKIP_LOCKED) != 0); } else skipped = !lazy_vacuum_rel(onerel, options, params, vac_strategy); diff --git a/src/include/commands/cluster.h b/src/include/commands/cluster.h index b338cb1098..49bb35fafe 100644 --- a/src/include/commands/cluster.h +++ b/src/include/commands/cluster.h @@ -19,8 +19,8 @@ extern void cluster(ClusterStmt *stmt, bool isTopLevel); -extern void cluster_rel(Oid tableOid, Oid indexOid, bool recheck, - bool verbose); +extern bool cluster_rel(Oid tableOid, Oid indexOid, bool recheck, + bool verbose, bool skip_locked); extern void check_index_is_clusterable(Relation OldHeap, Oid indexOid, bool recheck, LOCKMODE lockmode); extern void mark_index_clustered(Relation rel, Oid indexOid, bool is_internal); -- 2.16.2