v31--v32-dif-for-0001.patch
text/x-patch
Filename: v31--v32-dif-for-0001.patch
Type: text/x-patch
Part: 2
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v31-0002
Subject: fixes for 0001 patch
| File | + | − |
|---|---|---|
| src/backend/access/common/reloptions.c | 2 | 2 |
| src/backend/access/heap/vacuumlazy.c | 4 | 1 |
| src/backend/commands/vacuumparallel.c | 36 | 16 |
| src/backend/postmaster/autovacuum.c | 21 | 15 |
| src/backend/utils/init/globals.c | 1 | 1 |
| src/backend/utils/misc/guc.c | 4 | 3 |
| src/backend/utils/misc/guc_parameters.dat | 1 | 1 |
| src/backend/utils/misc/postgresql.conf.sample | 1 | 1 |
| src/test/modules/test_autovacuum/t/001_parallel_autovacuum.pl | 13 | 9 |
From 3954e445a3e794ef19dbccb699a0e61d36a33733 Mon Sep 17 00:00:00 2001
From: Daniil Davidov <d.davydov@postgrespro.ru>
Date: Sat, 28 Mar 2026 15:32:01 +0700
Subject: [PATCH 2/2] fixes for 0001 patch
---
src/backend/access/common/reloptions.c | 4 +-
src/backend/access/heap/vacuumlazy.c | 5 +-
src/backend/commands/vacuumparallel.c | 52 +++++++++++++------
src/backend/postmaster/autovacuum.c | 36 +++++++------
src/backend/utils/init/globals.c | 2 +-
src/backend/utils/misc/guc.c | 7 +--
src/backend/utils/misc/guc_parameters.dat | 2 +-
src/backend/utils/misc/postgresql.conf.sample | 2 +-
.../t/001_parallel_autovacuum.pl | 22 ++++----
9 files changed, 83 insertions(+), 49 deletions(-)
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index ce41b015b32..56dc99bdbe1 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -239,11 +239,11 @@ static relopt_int intRelOpts[] =
{
{
"autovacuum_parallel_workers",
- "Overrides value of the autovacuum_max_parallel_workers parameter for this table, if > -1.",
+ "Maximum number of parallel autovacuum workers that can be used for processing this table.",
RELOPT_KIND_HEAP,
ShareUpdateExclusiveLock
},
- 0, -1, 1024
+ -1, -1, 1024
},
{
{
diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c
index 8c7de657976..9fd4f6febbe 100644
--- a/src/backend/access/heap/vacuumlazy.c
+++ b/src/backend/access/heap/vacuumlazy.c
@@ -864,8 +864,11 @@ heap_vacuum_rel(Relation rel, const VacuumParams params,
dead_items_alloc(vacrel, params.nworkers);
#ifdef USE_INJECTION_POINTS
+
/*
- * Trigger injection point, if parallel autovacuum is about to be started.
+ * Used by tests to pause before parallel vacuum is launched, allowing
+ * test code to modify configuration that the leader then propagates to
+ * workers.
*/
if (AmAutoVacuumWorkerProcess() && ParallelVacuumIsActive(vacrel))
INJECTION_POINT("autovacuum-start-parallel-vacuum", NULL);
diff --git a/src/backend/commands/vacuumparallel.c b/src/backend/commands/vacuumparallel.c
index 62b6f50b538..13544de5b93 100644
--- a/src/backend/commands/vacuumparallel.c
+++ b/src/backend/commands/vacuumparallel.c
@@ -69,10 +69,12 @@ typedef struct PVSharedCostParams
{
/*
* The generation counter is incremented by the leader process each time
- * it updates the shared cost-based vacuum delay parameters. Paralell
+ * it updates the shared cost-based vacuum delay parameters. Parallel
* vacuum workers compares it with their local generation,
* shared_params_generation_local, to detect whether they need to refresh
- * their local parameters.
+ * their local parameters. The generation starts from 1 so that a freshly
+ * started worker (whose local copy is 0) will always load the initial
+ * parameters on its first check.
*/
pg_atomic_uint32 generation;
@@ -158,13 +160,13 @@ typedef struct PVShared
/*
* If 'true' then we are running parallel autovacuum. Otherwise, we are
- * running parallel maintenence VACUUM.
+ * running parallel maintenance VACUUM.
*/
bool is_autovacuum;
/*
- * Struct for syncing cost-based vacuum delay parameters between
- * supportive parallel autovacuum workers with leader worker.
+ * Cost-based vacuum delay parameters shared between the autovacuum leader
+ * and its parallel workers.
*/
PVSharedCostParams cost_params;
} PVShared;
@@ -271,7 +273,13 @@ struct ParallelVacuumState
static PVSharedCostParams *pv_shared_cost_params = NULL;
-/* See comments in the PVSharedCostParams for the details */
+/*
+ * Worker-local copy of the last cost-parameter generation this worker has
+ * applied. Initialized to 0; since the leader initializes the shared
+ * generation counter to 1, the first call to
+ * parallel_vacuum_update_shared_delay_params() will always detect a
+ * mismatch and read the initial parameters from shared memory.
+ */
static uint32 shared_params_generation_local = 0;
static int parallel_vacuum_compute_workers(Relation *indrels, int nindexes, int nrequested,
@@ -455,7 +463,7 @@ parallel_vacuum_init(Relation rel, Relation *indrels, int nindexes,
if (shared->is_autovacuum)
{
parallel_vacuum_set_cost_parameters(&shared->cost_params);
- pg_atomic_init_u32(&shared->cost_params.generation, 0);
+ pg_atomic_init_u32(&shared->cost_params.generation, 1);
SpinLockInit(&shared->cost_params.mutex);
pv_shared_cost_params = &(shared->cost_params);
@@ -623,7 +631,7 @@ parallel_vacuum_set_cost_parameters(PVSharedCostParams *params)
* Updates the cost-based vacuum delay parameters for parallel autovacuum
* workers.
*
- * For non-autovacuum parallel worker this function will have no effect.
+ * For non-autovacuum parallel workers, this function will have no effect.
*/
void
parallel_vacuum_update_shared_delay_params(void)
@@ -632,7 +640,7 @@ parallel_vacuum_update_shared_delay_params(void)
Assert(IsParallelWorker());
- /* Quick return if the wokrer is not running for the autovacuum */
+ /* Quick return if the worker is not running for the autovacuum */
if (pv_shared_cost_params == NULL)
return;
@@ -681,7 +689,7 @@ parallel_vacuum_propagate_shared_delay_params(void)
return;
/*
- * Check if any delay parameters has changed. We can read them without
+ * Check if any delay parameters have changed. We can read them without
* locks as only the leader can modify them.
*/
if (vacuum_cost_delay == pv_shared_cost_params->cost_delay &&
@@ -905,9 +913,10 @@ parallel_vacuum_process_all_indexes(ParallelVacuumState *pvs, int num_index_scan
}
#ifdef USE_INJECTION_POINTS
+
/*
- * This injection point is used to wait until parallel autovacuum workers
- * finishes their part of index processing.
+ * Used by tests to pause after workers are launched but before index
+ * vacuuming begins.
*/
if (nworkers > 0)
INJECTION_POINT("autovacuum-leader-before-indexes-processing", NULL);
@@ -1247,15 +1256,26 @@ parallel_vacuum_main(dsm_segment *seg, shm_toc *toc)
shared->dead_items_handle);
/* Set cost-based vacuum delay */
- VacuumUpdateCosts();
+ if (shared->is_autovacuum)
+ {
+ /*
+ * Parallel autovacuum workers initialize cost-based delay parameters
+ * from the leader's shared state rather than GUC defaults, because
+ * the leader may have applied per-table or autovacuum-specific
+ * overrides. pv_shared_cost_params must be set before calling
+ * parallel_vacuum_update_shared_delay_params().
+ */
+ pv_shared_cost_params = &(shared->cost_params);
+ parallel_vacuum_update_shared_delay_params();
+ }
+ else
+ VacuumUpdateCosts();
+
VacuumCostBalance = 0;
VacuumCostBalanceLocal = 0;
VacuumSharedCostBalance = &(shared->cost_balance);
VacuumActiveNWorkers = &(shared->active_nworkers);
- if (shared->is_autovacuum)
- pv_shared_cost_params = &(shared->cost_params);
-
/* Set parallel vacuum state */
pvs.indrels = indrels;
pvs.nindexes = nindexes;
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 3124341721c..ced4970a3a8 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2869,7 +2869,6 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
int multixact_freeze_table_age;
int log_vacuum_min_duration;
int log_analyze_min_duration;
- int nparallel_workers = -1; /* disabled by default */
/*
* Calculate the vacuum cost parameters and the freeze ages. If there
@@ -2930,19 +2929,6 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
tab->at_params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
tab->at_params.truncate = VACOPTVALUE_UNSPECIFIED;
- /* Decide whether we need to process indexes of table in parallel. */
- if (avopts)
- {
- if (avopts->autovacuum_parallel_workers > 0)
- nparallel_workers = avopts->autovacuum_parallel_workers;
- else if (avopts->autovacuum_parallel_workers == -1)
- {
- nparallel_workers = autovacuum_max_parallel_workers > 0
- ? autovacuum_max_parallel_workers
- : -1; /* disable parallelism if parameter's value is 0 */
- }
- }
-
tab->at_params.freeze_min_age = freeze_min_age;
tab->at_params.freeze_table_age = freeze_table_age;
tab->at_params.multixact_freeze_min_age = multixact_freeze_min_age;
@@ -2951,7 +2937,27 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
tab->at_params.log_vacuum_min_duration = log_vacuum_min_duration;
tab->at_params.log_analyze_min_duration = log_analyze_min_duration;
tab->at_params.toast_parent = InvalidOid;
- tab->at_params.nworkers = nparallel_workers;
+
+ /* Determine the number of parallel vacuum workers to use */
+ tab->at_params.nworkers = 0;
+ if (avopts)
+ {
+ if (avopts->autovacuum_parallel_workers == 0)
+ {
+ /*
+ * Disable parallel vacuum, if the reloption sets the parallel
+ * degree as zero.
+ */
+ tab->at_params.nworkers = -1;
+ }
+ else if (avopts->autovacuum_parallel_workers > 0)
+ tab->at_params.nworkers = avopts->autovacuum_parallel_workers;
+
+ /*
+ * autovacuum_parallel_workers == -1 falls through, keep
+ * nworkers=0
+ */
+ }
/*
* Later, in vacuum_rel(), we check reloptions for any
diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c
index 8265a82b639..24ddb276f0c 100644
--- a/src/backend/utils/init/globals.c
+++ b/src/backend/utils/init/globals.c
@@ -143,7 +143,7 @@ int NBuffers = 16384;
int MaxConnections = 100;
int max_worker_processes = 8;
int max_parallel_workers = 8;
-int autovacuum_max_parallel_workers = 2;
+int autovacuum_max_parallel_workers = 0;
int MaxBackends = 0;
/* GUC parameters for vacuum */
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 45b39b7c47f..1ac8e8fc3be 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -3359,9 +3359,10 @@ set_config_with_handle(const char *name, config_handle *handle,
* Also allow normal setting if the GUC is marked GUC_ALLOW_IN_PARALLEL.
*
* Other changes might need to affect other workers, so forbid them. Note,
- * that parallel autovacuum leader is an exception, because only
- * cost-based delays need to be affected also to parallel autovacuum
- * workers, and we will handle it elsewhere if appropriate.
+ * that parallel autovacuum leader is an exception because only cost-based
+ * delays need to be affected also to parallel autovacuum workers. These
+ * parameters are propagated to its workers during parallel vacuum (see
+ * vacuumparallel.c for details).
*/
if (IsInParallelMode() && !AmAutoVacuumWorkerProcess() && changeVal &&
action != GUC_ACTION_SAVE &&
diff --git a/src/backend/utils/misc/guc_parameters.dat b/src/backend/utils/misc/guc_parameters.dat
index e16c756e2cc..6ef46d88155 100644
--- a/src/backend/utils/misc/guc_parameters.dat
+++ b/src/backend/utils/misc/guc_parameters.dat
@@ -173,7 +173,7 @@
{ name => 'autovacuum_max_parallel_workers', type => 'int', context => 'PGC_SIGHUP', group => 'VACUUM_AUTOVACUUM',
short_desc => 'Maximum number of parallel workers that can be used by a single autovacuum worker.',
variable => 'autovacuum_max_parallel_workers',
- boot_val => '2',
+ boot_val => '0',
min => '0',
max => 'MAX_PARALLEL_WORKER_LIMIT',
},
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 6097d967ec1..73c49f09aef 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -713,7 +713,7 @@
#autovacuum_worker_slots = 16 # autovacuum worker slots to allocate
# (change requires restart)
#autovacuum_max_workers = 3 # max number of autovacuum subprocesses
-#autovacuum_max_parallel_workers = 2 # limited by max_parallel_workers
+#autovacuum_max_parallel_workers = 0 # limited by max_parallel_workers
#autovacuum_naptime = 1min # time between autovacuum runs
#autovacuum_vacuum_threshold = 50 # min number of row updates before
# vacuum
diff --git a/src/test/modules/test_autovacuum/t/001_parallel_autovacuum.pl b/src/test/modules/test_autovacuum/t/001_parallel_autovacuum.pl
index 0364019d5f0..2aca32374a2 100644
--- a/src/test/modules/test_autovacuum/t/001_parallel_autovacuum.pl
+++ b/src/test/modules/test_autovacuum/t/001_parallel_autovacuum.pl
@@ -12,7 +12,7 @@ if ($ENV{enable_injection_points} ne 'yes')
# Before each test we should disable autovacuum for 'test_autovac' table and
# generate some dead tuples in it. Returns the current autovacuum_count of
-# the table tset_autovac.
+# the table test_autovac.
sub prepare_for_next_test
{
my ($node, $test_number) = @_;
@@ -47,16 +47,20 @@ my $psql_out;
my $node = PostgreSQL::Test::Cluster->new('main');
$node->init;
-# Configure postgres, so it can launch parallel autovacuum workers, log all
-# information we are interested in and autovacuum works frequently
+# Limit to one autovacuum worker and disable autovacuum logging globally
+# (enabled only on the test table) so that log checks below match only
+# activity on the expected table.
$node->append_conf(
'postgresql.conf', qq{
- max_worker_processes = 20
- max_parallel_workers = 20
- autovacuum_max_parallel_workers = 4
- log_min_messages = debug2
- autovacuum_naptime = '1s'
- min_parallel_index_scan_size = 0
+autovacuum_max_workers = 1
+autovacuum_worker_slots = 1
+autovacuum_max_parallel_workers = 2
+max_worker_processes = 10
+max_parallel_workers = 10
+log_min_messages = debug2
+autovacuum_naptime = '1s'
+min_parallel_index_scan_size = 0
+log_autovacuum_min_duration = -1
});
$node->start;
--
2.43.0