From 8e7133f6ed928047f4befc58535e59a8931064bb Mon Sep 17 00:00:00 2001
From: Shinya Kato <shinya11.kato@gmail.com>
Date: Sat, 23 May 2026 14:24:41 +0900
Subject: [PATCH v1] Add autovacuum_warning to report concurrent vacuum
 collisions

Introduce a new GUC, autovacuum_warning (off by default), that logs a
message when an autovacuum worker attempts to process a table that is
already being vacuumed by another worker.  Such collisions are a sign
that autovacuum may not be keeping up, so surfacing them helps operators
diagnose the situation.  This is modeled after checkpoint_warning, which
similarly logs when checkpoints occur too frequently.

The message carries a generic hint to tune the autovacuum configuration,
since a collision has no single root cause and naming one parameter
could be misleading.

Author: Shinya Kato <shinya11.kato@gmail.com>
Reviewed-by:
Discussion: https://postgr.es/m/
---
 src/backend/postmaster/autovacuum.c           | 7 +++++++
 src/backend/utils/misc/guc_parameters.dat     | 7 +++++++
 src/backend/utils/misc/postgresql.conf.sample | 1 +
 src/include/postmaster/autovacuum.h           | 1 +
 4 files changed, 16 insertions(+)

diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index a5a8db2ff88..6f3bf1e498f 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -141,6 +141,7 @@ double		autovacuum_vacuum_insert_score_weight = 1.0;
 double		autovacuum_analyze_score_weight = 1.0;
 double		autovacuum_vac_cost_delay;
 int			autovacuum_vac_cost_limit;
+bool		autovacuum_warning;
 
 int			Log_autovacuum_min_duration = 600000;
 int			Log_autoanalyze_min_duration = 600000;
@@ -2424,6 +2425,12 @@ do_autovacuum(void)
 		LWLockRelease(AutovacuumLock);
 		if (skipit)
 		{
+			if (autovacuum_warning)
+				ereport(LOG,
+						(errmsg("autovacuum: table \"%s.%s\" is already being vacuumed by another worker",
+								get_namespace_name(get_rel_namespace(relid)),
+								get_rel_name(relid)),
+						 errhint("Consider tuning the autovacuum configuration parameters.")));
 			LWLockRelease(AutovacuumScheduleLock);
 			continue;
 		}
diff --git a/src/backend/utils/misc/guc_parameters.dat b/src/backend/utils/misc/guc_parameters.dat
index afaa058b046..bd35dfab839 100644
--- a/src/backend/utils/misc/guc_parameters.dat
+++ b/src/backend/utils/misc/guc_parameters.dat
@@ -289,6 +289,13 @@
   max => 'INT_MAX',
 },
 
+{ name => 'autovacuum_warning', type => 'bool', context => 'PGC_SIGHUP', group => 'VACUUM_AUTOVACUUM',
+  short_desc => 'Enables warnings when autovacuum cannot keep up.',
+  long_desc => 'Write a message to the server log if autovacuum attempts to process a table that is already being vacuumed by another worker.',
+  variable => 'autovacuum_warning',
+  boot_val => 'false',
+},
+
 { name => 'autovacuum_work_mem', type => 'int', context => 'PGC_SIGHUP', group => 'RESOURCES_MEM',
   short_desc => 'Sets the maximum memory to be used by each autovacuum worker process.',
   long_desc => '-1 means use "maintenance_work_mem".',
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index ac38cddaaf9..44375fd429d 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -756,6 +756,7 @@
 #autovacuum_vacuum_cost_limit = -1      # default vacuum cost limit for
                                         # autovacuum, -1 means use
                                         # vacuum_cost_limit
+#autovacuum_warning = off               # warn when autovacuum can't keep up
 
 # - Cost-Based Vacuum Delay -
 
diff --git a/src/include/postmaster/autovacuum.h b/src/include/postmaster/autovacuum.h
index 8954f6b28ee..fa2ec5ef97d 100644
--- a/src/include/postmaster/autovacuum.h
+++ b/src/include/postmaster/autovacuum.h
@@ -48,6 +48,7 @@ extern PGDLLIMPORT double autovacuum_multixact_freeze_score_weight;
 extern PGDLLIMPORT double autovacuum_vacuum_score_weight;
 extern PGDLLIMPORT double autovacuum_vacuum_insert_score_weight;
 extern PGDLLIMPORT double autovacuum_analyze_score_weight;
+extern PGDLLIMPORT bool autovacuum_warning;
 extern PGDLLIMPORT int Log_autovacuum_min_duration;
 extern PGDLLIMPORT int Log_autoanalyze_min_duration;
 
-- 
2.47.3

