Ever since we split the statistics collector's reports into per-database
files (commit
187492b6c2e8cafc), backends have been seeing stale statistics
for shared catalogs. This is because the inquiry message only prompts the
collector to write the per-database file for the requesting backend's own
database. Stats for shared catalogs are in a separate file for "DB 0",
which didn't get updated.
In normal operation this was partially masked by the fact that the
autovacuum launcher would send an inquiry message at least once per
autovacuum_naptime that asked for "DB 0"; so the shared-catalog stats would
never be more than a minute out of date. However the problem becomes very
obvious with autovacuum disabled, as reported by Peter Eisentraut.
To fix, redefine the semantics of inquiry messages so that both the
specified DB and DB 0 will be dumped. (This might seem a bit inefficient,
but we have no good way to know whether a backend's transaction will look
at shared-catalog stats, so we have to read both groups of stats whenever
we request stats. Sending two inquiry messages would definitely not be
better.)
Back-patch to 9.3 where the bug was introduced.
Report: <
56AD41AC.
1030509@gmx.net>
{
slist_iter iter;
- /* Check the databases if they need to refresh the stats. */
+ /*
+ * If any requests are outstanding at all, we should write the stats for
+ * shared catalogs (the "database" with OID 0). This ensures that
+ * backends will see up-to-date stats for shared catalogs, even though
+ * they send inquiry messages mentioning only their own DB.
+ */
+ if (databaseid == InvalidOid && !slist_is_empty(&last_statrequests))
+ return true;
+
+ /* Search to see if there's an open request to write this database. */
slist_foreach(iter, &last_statrequests)
{
DBWriteRequest *req = slist_container(DBWriteRequest, next, iter.cur);