From 6f29356c60a6f44c4f2eaa56cf1e32b9c4f25524 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Thu, 5 Apr 2018 19:00:40 +0000 Subject: [PATCH v7 08/12] Skip VACUUM/ANALYZE with VACOPT_SKIP_LOCKED if indexes can't be opened. --- src/backend/commands/analyze.c | 29 ++++++++++++++++++++++++----- src/backend/commands/vacuum.c | 23 +++++++++++++++++++---- src/backend/commands/vacuumlazy.c | 23 +++++++++++++++++++++-- src/include/commands/vacuum.h | 2 +- 4 files changed, 65 insertions(+), 12 deletions(-) diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index 03e0bad1f3..0421d77ad7 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -84,7 +84,7 @@ static BufferAccessStrategy vac_strategy; static void do_analyze_rel(Relation onerel, int options, VacuumParams *params, List *va_cols, AcquireSampleRowsFunc acquirefunc, BlockNumber relpages, - bool inh, bool in_outer_xact, int elevel); + bool inh, bool in_outer_xact, int elevel, RangeVar *rangeVar); static void compute_index_stats(Relation onerel, double totalrows, AnlIndexData *indexdata, int nindexes, HeapTuple *rows, int numrows, @@ -294,14 +294,14 @@ analyze_rel(Oid relid, RangeVar *relation, int options, */ if (onerel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) do_analyze_rel(onerel, options, params, va_cols, acquirefunc, - relpages, false, in_outer_xact, elevel); + relpages, false, in_outer_xact, elevel, relation); /* * If there are child tables, do recursive ANALYZE. */ if (onerel->rd_rel->relhassubclass) do_analyze_rel(onerel, options, params, va_cols, acquirefunc, relpages, - true, in_outer_xact, elevel); + true, in_outer_xact, elevel, relation); /* * Close source relation now, but keep lock so that no one deletes it @@ -331,7 +331,7 @@ static void do_analyze_rel(Relation onerel, int options, VacuumParams *params, List *va_cols, AcquireSampleRowsFunc acquirefunc, BlockNumber relpages, bool inh, bool in_outer_xact, - int elevel) + int elevel, RangeVar *rangeVar) { int attr_cnt, tcnt, @@ -454,7 +454,26 @@ do_analyze_rel(Relation onerel, int options, VacuumParams *params, * all. */ if (!inh) - vac_open_indexes(onerel, AccessShareLock, &nindexes, &Irel, false, NULL); + { + bool skipped = false; + + vac_open_indexes(onerel, AccessShareLock, &nindexes, &Irel, + (options & VACOPT_SKIP_LOCKED), &skipped); + + /* + * If SKIP LOCKED is specified and we would have to wait for a lock on + * an index, skip analyzing the relation. + */ + if (skipped) + { + do_analyze_rel_cleanup(save_nestlevel, save_userid, + save_sec_context, caller_context, + rangeVar, params); + + return; + } + + } else { Irel = NULL; diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index d7967dda6b..fb7dd8d536 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -1314,6 +1314,7 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params) int save_sec_context; int save_nestlevel; bool rel_lock = true; + bool skipped = false; Assert(params != NULL); @@ -1539,7 +1540,18 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params) (options & VACOPT_VERBOSE) != 0); } else - lazy_vacuum_rel(onerel, options, params, vac_strategy); + skipped = !lazy_vacuum_rel(onerel, options, params, vac_strategy); + + if (skipped) + { + int elevel = get_elevel_for_skipped_relation(relation, params); + + if (elevel != 0) + ereport(elevel, + (errcode(ERRCODE_LOCK_NOT_AVAILABLE), + errmsg("skipping vacuum of \"%s\" --- lock not available", + relation->relname))); + } /* Roll back any GUC changes executed by index functions */ AtEOXact_GUC(false, save_nestlevel); @@ -1563,8 +1575,11 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params) * "analyze" will not get done on the toast table. This is good, because * the toaster always uses hardcoded index access and statistics are * totally unimportant for toast relations. + * + * If we skipped vacuuming the main relation, skip vacuuming the secondary + * toast rel as well. */ - if (toast_relid != InvalidOid) + if (!skipped && toast_relid != InvalidOid) vacuum_rel(toast_relid, NULL, options, params); /* @@ -1572,8 +1587,8 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params) */ UnlockRelationIdForSession(&onerelid, lmode); - /* Report that we really did it. */ - return true; + /* Report if we really did it. */ + return !skipped; } diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index 13e5bd452f..3a584b5115 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -186,8 +186,12 @@ static bool heap_page_is_all_visible(Relation rel, Buffer buf, * * At entry, we have already established a transaction and opened * and locked the relation. + * + * If SKIP LOCKED is specified in the options and lazy_vacuum_rel() + * skips the relation due to a conflicting lock, false is returned. + * Else, true is returned. */ -void +bool lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params, BufferAccessStrategy bstrategy) { @@ -209,6 +213,7 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params, double new_live_tuples; TransactionId new_frozen_xid; MultiXactId new_min_multi; + bool skipped = false; Assert(params != NULL); @@ -259,7 +264,19 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params, vacrelstats->lock_waiter_detected = false; /* Open all indexes of the relation */ - vac_open_indexes(onerel, RowExclusiveLock, &nindexes, &Irel, false, NULL); + vac_open_indexes(onerel, RowExclusiveLock, &nindexes, &Irel, + (options & VACOPT_SKIP_LOCKED), &skipped); + + /* + * If SKIP LOCKED is specified and we would have to wait for a lock on an + * index, skip vacuuming the relation. + */ + if (skipped) + { + pgstat_progress_end_command(); + return false; + } + vacrelstats->hasindex = (nindexes > 0); /* Do the vacuuming */ @@ -409,6 +426,8 @@ lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params, pfree(buf.data); } } + + return true; } /* diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index 64215ea60a..23fd8392c5 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -189,7 +189,7 @@ extern void vacuum_delay_point(void); extern int get_elevel_for_skipped_relation(RangeVar *relation, VacuumParams *params); /* in commands/vacuumlazy.c */ -extern void lazy_vacuum_rel(Relation onerel, int options, +extern bool lazy_vacuum_rel(Relation onerel, int options, VacuumParams *params, BufferAccessStrategy bstrategy); /* in commands/analyze.c */ -- 2.16.2