postgres.git / summary / log / commit / refs

commit    42e96cf2fe095c822f76bc94669ea875cb1e3351
Author:   Masahiko Sawada <msawada@postgresql.org>
Date:     Thu Oct 01 13:19:23 2026 +0000

    Refresh autovacuum costs while waiting for parallel workers.
    
    Commit 1ff3180ca01 made a parallel autovacuum leader propagate changes
    to the cost-based delay parameters to its workers only from
    vacuum_delay_point(), which it no longer reaches once it is waiting in
    WaitForParallelWorkersToFinish(). While waiting, the leader neither
    processed a config reload nor noticed a change in the number of
    autovacuum workers sharing the cost limit, so its workers kept running
    with stale parameters until they finished.
    
    Fix by refreshing and propagating the parameters on every wakeup of
    that wait loop, and by setting the latches of the balanced autovacuum
    workers when their count changes so that a waiting leader wakes up.
    
    A regression test will be added in a separate commit.
    
    Backpatch to v19, where parallel autovacuum was introduced.
    
    Reported-by: Nikolay Samokhvalov <nik@postgres.ai>
    Author: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
    Reviewed-by: Manu <manuelreyesbravo@gmail.com>
    Reviewed-by: Zsolt Parragi <zsolt.parragi@percona.com>
    Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
    Reviewed-by: Masahiko Sawada <sawada.mshk@gmail.com>
    Discussion: https://postgr.es/m/CAM527d-GL=Jp2EJXBSnVBGPK-4XEZwWof5Cv8P0hghS_og6oAg@mail.gmail.com
    Backpatch-through: 19


src/backend/access/transam/parallel.c | 11 +++++++++++ src/backend/commands/vacuumparallel.c | 35 +++++++++++++++++++++++++++++++++++ src/backend/postmaster/autovacuum.c | 25 +++++++++++++++++++++++++ src/include/commands/vacuum.h | 1 + 4 files changed, 72 insertions(+) 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 */ [parent: adffcab923e1]