diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c index e1806a9a28a..b51df2a4606 100644 --- a/src/backend/access/transam/parallel.c +++ b/src/backend/access/transam/parallel.c @@ -812,6 +812,17 @@ WaitForParallelWorkersToFinish(ParallelContext *pcxt) */ CHECK_FOR_INTERRUPTS(); + /* + * An autovacuum worker running a parallel vacuum (leader) propagates + * changes to the cost-based delay parameters to its parallel workers + * at its own cost delay points, which it no longer reaches while + * waiting here. Do it here instead, on every wakeup, so that a config + * reload or a change in the number of autovacuum workers sharing the + * cost limit reaches the parallel workers before they finish. + */ + if (AmAutoVacuumWorkerProcess()) + parallel_vacuum_refresh_cost_params(); + for (i = 0; i < pcxt->nworkers_launched; ++i) { /* diff --git a/src/backend/commands/vacuumparallel.c b/src/backend/commands/vacuumparallel.c index d4572861000..da0ec3cc8ee 100644 --- a/src/backend/commands/vacuumparallel.c +++ b/src/backend/commands/vacuumparallel.c @@ -43,6 +43,7 @@ #include "executor/instrument.h" #include "optimizer/paths.h" #include "pgstat.h" +#include "postmaster/interrupt.h" #include "storage/bufmgr.h" #include "storage/proc.h" #include "tcop/tcopprot.h" @@ -729,6 +730,40 @@ parallel_vacuum_propagate_shared_delay_params(void) pg_atomic_fetch_add_u32(&pv_shared_cost_params->generation, 1); } +/* + * Reload the configuration file if requested, and refresh the cost-based + * delay parameters of an autovacuum worker running a parallel vacuum + * (leader), propagating any change to its parallel workers. + */ +void +parallel_vacuum_refresh_cost_params(void) +{ + Assert(AmAutoVacuumWorkerProcess()); + + /* + * Quick return if the leader is not sharing the delay parameters with + * parallel workers. + */ + if (pv_shared_cost_params == NULL) + return; + + if (ConfigReloadPending) + { + ConfigReloadPending = false; + ProcessConfigFile(PGC_SIGHUP); + + /* This re-divides the cost limit too */ + VacuumUpdateCosts(); + } + else + { + /* The number of workers sharing the cost limit may have changed */ + AutoVacuumUpdateCostLimit(); + } + + parallel_vacuum_propagate_shared_delay_params(); +} + /* * Compute the number of parallel worker processes to request. Both index * vacuum and index cleanup can be executed with parallel workers. diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 60ebe828900..0ec01c5da6f 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -1814,8 +1814,33 @@ autovac_recalculate_workers_for_balance(void) } if (nworkers_for_balance != orig_nworkers_for_balance) + { pg_atomic_write_u32(&AutoVacuumShmem->av_nworkersForBalance, nworkers_for_balance); + + /* + * Wake up the autovacuum workers sharing the cost limit so that they + * pick up the new count. An autovacuum worker that is vacuuming does + * that on its next nap anyway, but one running a parallel vacuum + * (leader) that is only waiting for its parallel workers to finish + * never naps, and nothing else would tell it. + * + * Only the waiting leaders need this, but knowing which ones are + * waiting would need more state. For an autovacuum worker that is not + * in a latch wait, SetLatch() sends no signal and only marks the + * latch set, which costs one early return from its next latch wait. + */ + dlist_foreach(iter, &AutoVacuumShmem->av_runningWorkers) + { + WorkerInfo worker = dlist_container(WorkerInfoData, wi_links, iter.cur); + + if (worker->wi_proc == NULL || + pg_atomic_unlocked_test_flag(&worker->wi_dobalance)) + continue; + + SetLatch(&worker->wi_proc->procLatch); + } + } } /* diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index 6e3c912bf5c..89fa1fcd261 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -432,6 +432,7 @@ extern void parallel_vacuum_cleanup_all_indexes(ParallelVacuumState *pvs, PVWorkerStats *wstats); extern void parallel_vacuum_update_shared_delay_params(void); extern void parallel_vacuum_propagate_shared_delay_params(void); +extern void parallel_vacuum_refresh_cost_params(void); extern void parallel_vacuum_main(dsm_segment *seg, shm_toc *toc); /* in commands/analyze.c */