Avoid having autovacuum read pgstats data too many times in quick succession.
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 24 Sep 2007 04:12:01 +0000 (04:12 +0000)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 24 Sep 2007 04:12:01 +0000 (04:12 +0000)
This is problematic for the autovac launcher when there are many databases,
so we keep data for a full second before reading it again.

src/backend/postmaster/autovacuum.c

index 7c9b7f72b6cdbfd2b805fbb80cbfa1c74f1cb77c..bce0ba4323ff02b17b5acf6a43897db4e930eb79 100644 (file)
@@ -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();
+}