static void analyze_rel_coordinator(Relation onerel, bool inh, int attr_cnt,
VacAttrStats **vacattrstats, int nindexes,
Relation *indexes, AnlIndexData *indexdata);
-static void analyze_remote_coordinators(Relation onerel);
#endif
/*
void
analyze_rel(Oid relid, RangeVar *relation, int options,
VacuumParams *params, List *va_cols, bool in_outer_xact,
+ bool *need_remote_analyze,
BufferAccessStrategy bstrategy)
{
Relation onerel;
MyPgXact->vacuumFlags |= PROC_IN_ANALYZE;
LWLockRelease(ProcArrayLock);
+ /*
+ * If distribited relation, then ANALYZE (COORDINATOR) on the other
+ * coordinators is required.
+ */
+ if (onerel->rd_locator_info)
+ *need_remote_analyze = true;
+
/*
* Do the normal non-recursive ANALYZE. We can skip this for partitioned
* tables, which don't contain any rows.
analyze_rel_coordinator(onerel, inh, attr_cnt, vacattrstats,
nindexes, Irel, indexdata);
- /*
- * Run ANALYZE on remote coordinators as well.
- */
- analyze_remote_coordinators(onerel);
-
/*
* Skip acquiring local stats. Coordinator does not store data of
* distributed tables.
coord_collect_extended_stats(onerel, attr_cnt);
}
-static void
-analyze_remote_coordinators(Relation onerel)
+void
+analyze_remote_coordinators(Oid relid, RangeVar *relation, int options,
+ VacuumParams *params)
{
RemoteQuery *step;
StringInfoData sql;
+ Relation onerel;
if (IsConnFromCoord())
return;
+ if (!(options & VACOPT_NOWAIT))
+ onerel = try_relation_open(relid, ShareUpdateExclusiveLock);
+ else if (ConditionalLockRelationOid(relid, ShareUpdateExclusiveLock))
+ onerel = try_relation_open(relid, NoLock);
+ else
+ {
+ onerel = NULL;
+ if (relation &&
+ IsAutoVacuumWorkerProcess() && params->log_min_duration >= 0)
+ ereport(LOG,
+ (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
+ errmsg("skipping remote analyze of \"%s\" --- lock not available",
+ relation->relname)));
+ return;
+ }
/*
* Temporary tables are not available on remote coordinators.
*/
if (onerel->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
- return;
+ goto cleanup;
initStringInfo(&sql);
appendStringInfo(&sql, "ANALYZE (COORDINATOR) %s.%s",
/* Be sure to advance the command counter after the last command */
CommandCounterIncrement();
+
+cleanup:
+ relation_close(onerel, NoLock);
}
#endif
use_own_xacts;
List *relations;
static bool in_vacuum = false;
+ bool need_remote_analyze = false;
Assert(params != NULL);
}
analyze_rel(relid, relation, options, params,
- va_cols, in_outer_xact, vac_strategy);
+ va_cols, in_outer_xact, &need_remote_analyze,
+ vac_strategy);
if (use_own_xacts)
{
PopActiveSnapshot();
CommitTransactionCommand();
+
+ if (IS_PGXC_COORDINATOR && need_remote_analyze)
+ {
+ StartTransactionCommand();
+ PushActiveSnapshot(GetTransactionSnapshot());
+
+ /*
+ * Run ANALYZE on remote coordinators as well, if we're
+ * running in our own transaction. We have this
+ * restriction because the remote coordinator will
+ * connect to the datanodes, which may have the current
+ * transaction open originating from us and not
+ * prepared to handle a auxilliary connection from
+ * other coordinators.
+ *
+ * This implies that ANALYZE executed inside a user
+ * transaction block won't be sent down other
+ * coordinators and the stats may remain stale on those
+ * coordinators. But at the least, this takes care of
+ * cases of auto-analyzing and explicit ANALYZE outside
+ * a transaction block.
+ */
+ analyze_remote_coordinators(relid, relation, options,
+ params);
+
+ PopActiveSnapshot();
+ CommitTransactionCommand();
+
+ }
}
}
}
/* in commands/analyze.c */
extern void analyze_rel(Oid relid, RangeVar *relation, int options,
VacuumParams *params, List *va_cols, bool in_outer_xact,
+ bool *need_remote_analyze,
BufferAccessStrategy bstrategy);
extern bool std_typanalyze(VacAttrStats *stats);
+extern void analyze_remote_coordinators(Oid relid, RangeVar *relation,
+ int options, VacuumParams *params);
/* in utils/misc/sampling.c --- duplicate of declarations in utils/sampling.h */
extern double anl_random_fract(void);