From c181744cdf9c7970209013787b6e62fb5de5dac7 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Wed, 5 Sep 2018 14:44:15 +0000 Subject: [PATCH v9 5/7] Skip ANALYZE with VACOPT_SKIP_LOCKED if acquire_inherited_sample_rows() blocks. --- src/backend/commands/analyze.c | 62 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index 26fa7bcd55..bc215e7c00 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, @@ -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); @@ -284,14 +285,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 @@ -321,7 +322,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, @@ -343,6 +344,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, @@ -521,9 +523,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, @@ -1308,15 +1324,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; @@ -1334,7 +1355,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