v7-0009-Skip-ANALYZE-with-VACOPT_SKIP_LOCKED-if-acquire_i.patch
application/octet-stream
Filename: v7-0009-Skip-ANALYZE-with-VACOPT_SKIP_LOCKED-if-acquire_i.patch
Type: application/octet-stream
Part: 8
Message:
Re: BUG #14941: Vacuum crashes
Patch
Format: format-patch
Series: patch v7-0009
Subject: Skip ANALYZE with VACOPT_SKIP_LOCKED if acquire_inherited_sample_rows() blocks.
| File | + | − |
|---|---|---|
| src/backend/commands/analyze.c | 47 | 7 |
From 7ad5ee333bc8fee0c860be2ad537eeb5d5d728ce Mon Sep 17 00:00:00 2001
From: Nathan Bossart <bossartn@amazon.com>
Date: Thu, 5 Apr 2018 18:43:45 +0000
Subject: [PATCH v7 09/12] Skip ANALYZE with VACOPT_SKIP_LOCKED if
acquire_inherited_sample_rows() blocks.
---
src/backend/commands/analyze.c | 54 ++++++++++++++++++++++++++++++++++++------
1 file changed, 47 insertions(+), 7 deletions(-)
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 0421d77ad7..1997726fd1 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -97,7 +97,8 @@ static int acquire_sample_rows(Relation onerel, int elevel,
static int compare_rows(const void *a, const void *b);
static int acquire_inherited_sample_rows(Relation onerel, int elevel,
HeapTuple *rows, int targrows,
- double *totalrows, double *totaldeadrows);
+ double *totalrows, double *totaldeadrows,
+ bool skip_locked, bool *skipped);
static void update_attstats(Oid relid, bool inh,
int natts, VacAttrStats **vacattrstats);
static Datum std_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull);
@@ -353,6 +354,7 @@ do_analyze_rel(Relation onerel, int options, VacuumParams *params,
Oid save_userid;
int save_sec_context;
int save_nestlevel;
+ bool skipped = false;
if (inh)
ereport(elevel,
@@ -550,9 +552,23 @@ do_analyze_rel(Relation onerel, int options, VacuumParams *params,
*/
rows = (HeapTuple *) palloc(targrows * sizeof(HeapTuple));
if (inh)
+ {
numrows = acquire_inherited_sample_rows(onerel, elevel,
rows, targrows,
- &totalrows, &totaldeadrows);
+ &totalrows, &totaldeadrows,
+ (options & VACOPT_SKIP_LOCKED), &skipped);
+
+ /*
+ * If SKIP LOCKED is specified and we would have to wait for a lock on
+ * a child relation, skip analyzing the relation.
+ */
+ if (skipped)
+ {
+ do_analyze_rel_cleanup(save_nestlevel, save_userid, save_sec_context,
+ caller_context, rangeVar, params);
+ return;
+ }
+ }
else
numrows = (*acquirefunc) (onerel, elevel,
rows, targrows,
@@ -1337,15 +1353,20 @@ compare_rows(const void *a, const void *b)
/*
* acquire_inherited_sample_rows -- acquire sample rows from inheritance tree
*
- * This has the same API as acquire_sample_rows, except that rows are
+ * This has roughly the same API as acquire_sample_rows, except that rows are
* collected from all inheritance children as well as the specified table.
- * We fail and return zero if there are no inheritance children, or if all
- * children are foreign tables that don't support ANALYZE.
+ * We fail and return zero if there are no inheritance children, if all
+ * children are foreign tables that don't support ANALYZE, or if skip_locked
+ * is true and we cannot obtain a lock on all children without waiting.
+ *
+ * If skipped is supplied, it will be set to true if skip_locked takes effect
+ * (false otherwise).
*/
static int
acquire_inherited_sample_rows(Relation onerel, int elevel,
HeapTuple *rows, int targrows,
- double *totalrows, double *totaldeadrows)
+ double *totalrows, double *totaldeadrows,
+ bool skip_locked, bool *skipped)
{
List *tableOIDs;
Relation *rels;
@@ -1363,7 +1384,26 @@ acquire_inherited_sample_rows(Relation onerel, int elevel,
* the children.
*/
tableOIDs =
- find_all_inheritors(RelationGetRelid(onerel), AccessShareLock, NULL, false);
+ find_all_inheritors(RelationGetRelid(onerel), AccessShareLock, NULL, skip_locked);
+
+ /*
+ * If tableOIDs is NIL, skip_locked took effect. In that case, we should
+ * fail, being sure to set skipped if it is provided.
+ */
+ if (tableOIDs == NIL)
+ {
+ if (skipped != NULL)
+ *skipped = true;
+
+ return 0;
+ }
+
+ /*
+ * All skip_locked-related logic precedes this point, so we can just set
+ * skipped to false if it is provided.
+ */
+ if (skipped != NULL)
+ *skipped = false;
/*
* Check that there's at least one descendant, else fail. This could
--
2.16.2