v7-0008-Skip-VACUUM-ANALYZE-with-VACOPT_SKIP_LOCKED-if-in.patch
application/octet-stream
Filename: v7-0008-Skip-VACUUM-ANALYZE-with-VACOPT_SKIP_LOCKED-if-in.patch
Type: application/octet-stream
Part: 7
Message:
Re: BUG #14941: Vacuum crashes
Patch
Format: format-patch
Series: patch v7-0008
Subject: Skip VACUUM/ANALYZE with VACOPT_SKIP_LOCKED if indexes can't be opened.
| File | + | − |
|---|---|---|
| src/backend/commands/analyze.c | 24 | 5 |
| src/backend/commands/vacuum.c | 19 | 4 |
| src/backend/commands/vacuumlazy.c | 21 | 2 |
| src/include/commands/vacuum.h | 1 | 1 |
From 6f29356c60a6f44c4f2eaa56cf1e32b9c4f25524 Mon Sep 17 00:00:00 2001
From: Nathan Bossart <bossartn@amazon.com>
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