mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-29 22:49:41 +03:00 
			
		
		
		
	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.
This commit is contained in:
		| @@ -55,7 +55,7 @@ | |||||||
|  * |  * | ||||||
|  * |  * | ||||||
|  * IDENTIFICATION |  * 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; | 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 */ | /* Flags to tell if we are in an autovacuum process */ | ||||||
| static bool am_autovacuum_launcher = false; | 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_sigusr1_handler(SIGNAL_ARGS); | ||||||
| static void avl_sigterm_handler(SIGNAL_ARGS); | static void avl_sigterm_handler(SIGNAL_ARGS); | ||||||
| static void avl_quickdie(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; | 		DatabaseListCxt = NULL; | ||||||
| 		DatabaseList = 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(); | 		pgstat_clear_snapshot(); | ||||||
|  |  | ||||||
| 		/* Now we can allow interrupts again */ | 		/* Now we can allow interrupts again */ | ||||||
| @@ -836,7 +843,7 @@ rebuild_database_list(Oid newdb) | |||||||
| 	HTAB	   *dbhash; | 	HTAB	   *dbhash; | ||||||
|  |  | ||||||
| 	/* use fresh stats */ | 	/* use fresh stats */ | ||||||
| 	pgstat_clear_snapshot(); | 	autovac_refresh_stats(); | ||||||
|  |  | ||||||
| 	newcxt = AllocSetContextCreate(AutovacMemCxt, | 	newcxt = AllocSetContextCreate(AutovacMemCxt, | ||||||
| 								   "AV dblist", | 								   "AV dblist", | ||||||
| @@ -1063,7 +1070,7 @@ do_start_worker(void) | |||||||
| 	oldcxt = MemoryContextSwitchTo(tmpcxt); | 	oldcxt = MemoryContextSwitchTo(tmpcxt); | ||||||
|  |  | ||||||
| 	/* use fresh stats */ | 	/* use fresh stats */ | ||||||
| 	pgstat_clear_snapshot(); | 	autovac_refresh_stats(); | ||||||
|  |  | ||||||
| 	/* Get a list of databases */ | 	/* Get a list of databases */ | ||||||
| 	dblist = get_database_list(); | 	dblist = get_database_list(); | ||||||
| @@ -1106,9 +1113,6 @@ do_start_worker(void) | |||||||
| 		avw_dbase  *tmp = lfirst(cell); | 		avw_dbase  *tmp = lfirst(cell); | ||||||
| 		Dlelem	   *elem; | 		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 */ | 		/* Check to see if this one is at risk of wraparound */ | ||||||
| 		if (TransactionIdPrecedes(tmp->adw_frozenxid, xidForceLimit)) | 		if (TransactionIdPrecedes(tmp->adw_frozenxid, xidForceLimit)) | ||||||
| 		{ | 		{ | ||||||
| @@ -1121,9 +1125,12 @@ do_start_worker(void) | |||||||
| 		else if (for_xid_wrap) | 		else if (for_xid_wrap) | ||||||
| 			continue;			/* ignore not-at-risk DBs */ | 			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 | 		 * Skip a database with no pgstat entry; it means it hasn't seen any | ||||||
| 		 * hasn't seen any activity. | 		 * activity. | ||||||
| 		 */ | 		 */ | ||||||
| 		if (!tmp->adw_entry) | 		if (!tmp->adw_entry) | ||||||
| 			continue; | 			continue; | ||||||
| @@ -2258,7 +2265,7 @@ table_recheck_autovac(Oid relid) | |||||||
| 	PgStat_StatDBEntry *dbentry; | 	PgStat_StatDBEntry *dbentry; | ||||||
|  |  | ||||||
| 	/* use fresh stats */ | 	/* use fresh stats */ | ||||||
| 	pgstat_clear_snapshot(); | 	autovac_refresh_stats(); | ||||||
|  |  | ||||||
| 	shared = pgstat_fetch_stat_dbentry(InvalidOid); | 	shared = pgstat_fetch_stat_dbentry(InvalidOid); | ||||||
| 	dbentry = pgstat_fetch_stat_dbentry(MyDatabaseId); | 	dbentry = pgstat_fetch_stat_dbentry(MyDatabaseId); | ||||||
| @@ -2725,3 +2732,35 @@ AutoVacuumShmemInit(void) | |||||||
| 	else | 	else | ||||||
| 		Assert(found); | 		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(); | ||||||
|  | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user