Commit 45cbdaa0 authored by Alvaro Herrera's avatar Alvaro Herrera

Avoid having autovacuum read pgstats data too many times in quick succession.

This is problematic for the autovac launcher when there are many databases,
so we keep data for a full second before reading it again.
parent 58536626
......@@ -55,7 +55,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.60 2007/09/24 03:12:23 tgl Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.61 2007/09/24 04:12:01 alvherre Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -116,6 +116,9 @@ int autovacuum_vac_cost_limit;
int Log_autovacuum_min_duration = -1;
/* how long to keep pgstat data in the launcher, in milliseconds */
#define STATS_READ_DELAY 1000
/* Flags to tell if we are in an autovacuum process */
static bool am_autovacuum_launcher = false;
......@@ -291,6 +294,7 @@ static void avl_sighup_handler(SIGNAL_ARGS);
static void avl_sigusr1_handler(SIGNAL_ARGS);
static void avl_sigterm_handler(SIGNAL_ARGS);
static void avl_quickdie(SIGNAL_ARGS);
static void autovac_refresh_stats(void);
......@@ -488,7 +492,10 @@ AutoVacLauncherMain(int argc, char *argv[])
DatabaseListCxt = NULL;
DatabaseList = NULL;
/* Make sure pgstat also considers our stat data as gone */
/*
* Make sure pgstat also considers our stat data as gone. Note: we
* mustn't use autovac_refresh_stats here.
*/
pgstat_clear_snapshot();
/* Now we can allow interrupts again */
......@@ -836,7 +843,7 @@ rebuild_database_list(Oid newdb)
HTAB *dbhash;
/* use fresh stats */
pgstat_clear_snapshot();
autovac_refresh_stats();
newcxt = AllocSetContextCreate(AutovacMemCxt,
"AV dblist",
......@@ -1063,7 +1070,7 @@ do_start_worker(void)
oldcxt = MemoryContextSwitchTo(tmpcxt);
/* use fresh stats */
pgstat_clear_snapshot();
autovac_refresh_stats();
/* Get a list of databases */
dblist = get_database_list();
......@@ -1106,9 +1113,6 @@ do_start_worker(void)
avw_dbase *tmp = lfirst(cell);
Dlelem *elem;
/* Find pgstat entry if any */
tmp->adw_entry = pgstat_fetch_stat_dbentry(tmp->adw_datid);
/* Check to see if this one is at risk of wraparound */
if (TransactionIdPrecedes(tmp->adw_frozenxid, xidForceLimit))
{
......@@ -1121,9 +1125,12 @@ do_start_worker(void)
else if (for_xid_wrap)
continue; /* ignore not-at-risk DBs */
/* Find pgstat entry if any */
tmp->adw_entry = pgstat_fetch_stat_dbentry(tmp->adw_datid);
/*
* Otherwise, skip a database with no pgstat entry; it means it
* hasn't seen any activity.
* Skip a database with no pgstat entry; it means it hasn't seen any
* activity.
*/
if (!tmp->adw_entry)
continue;
......@@ -2258,7 +2265,7 @@ table_recheck_autovac(Oid relid)
PgStat_StatDBEntry *dbentry;
/* use fresh stats */
pgstat_clear_snapshot();
autovac_refresh_stats();
shared = pgstat_fetch_stat_dbentry(InvalidOid);
dbentry = pgstat_fetch_stat_dbentry(MyDatabaseId);
......@@ -2725,3 +2732,35 @@ AutoVacuumShmemInit(void)
else
Assert(found);
}
/*
* autovac_refresh_stats
* Refresh pgstats data for an autovacuum process
*
* Cause the next pgstats read operation to obtain fresh data, but throttle
* such refreshing in the autovacuum launcher. This is mostly to avoid
* rereading the pgstats files too many times in quick succession when there
* are many databases.
*
* Note: we avoid throttling in the autovac worker, as it would be
* counterproductive in the recheck logic.
*/
static void
autovac_refresh_stats(void)
{
if (IsAutoVacuumLauncherProcess())
{
static TimestampTz last_read = 0;
TimestampTz current_time;
current_time = GetCurrentTimestamp();
if (!TimestampDifferenceExceeds(last_read, current_time,
STATS_READ_DELAY))
return;
last_read = current_time;
}
pgstat_clear_snapshot();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment