From 2a67208c7f660f23eb302288b0b74cbb0e839011 Mon Sep 17 00:00:00 2001 From: Peter Geoghegan Date: Thu, 13 May 2021 17:53:10 -0700 Subject: [PATCH v1] Consider triggering failsafe during first scan. --- src/backend/access/heap/vacuumlazy.c | 34 ++++++++++++---------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 9f1f8e340d..2dd3fbe07a 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -110,10 +110,9 @@ #define BYPASS_THRESHOLD_PAGES 0.02 /* i.e. 2% of rel_pages */ /* - * When a table is small (i.e. smaller than this), save cycles by avoiding - * repeated failsafe checks + * Perform failsafe checks every 4GB, approximately */ -#define FAILSAFE_MIN_PAGES \ +#define FAILSAFE_EVERY_PAGES \ ((BlockNumber) (((uint64) 4 * 1024 * 1024 * 1024) / BLCKSZ)) /* @@ -890,6 +889,7 @@ lazy_scan_heap(LVRelState *vacrel, VacuumParams *params, bool aggressive) BlockNumber nblocks, blkno, next_unskippable_block, + next_failsafe_block, next_fsm_block_to_vacuum; PGRUsage ru0; Buffer vmbuffer = InvalidBuffer; @@ -919,6 +919,7 @@ lazy_scan_heap(LVRelState *vacrel, VacuumParams *params, bool aggressive) nblocks = RelationGetNumberOfBlocks(vacrel->rel); next_unskippable_block = 0; + next_failsafe_block = 0; next_fsm_block_to_vacuum = 0; vacrel->rel_pages = nblocks; vacrel->scanned_pages = 0; @@ -1168,6 +1169,15 @@ lazy_scan_heap(LVRelState *vacrel, VacuumParams *params, bool aggressive) PROGRESS_VACUUM_PHASE_SCAN_HEAP); } + /* + * Regularly consider if wraparound failsafe should trigger + */ + if (blkno - next_failsafe_block >= FAILSAFE_EVERY_PAGES) + { + lazy_check_wraparound_failsafe(vacrel); + next_failsafe_block = blkno; + } + /* * Set up visibility map page as needed. * @@ -1375,17 +1385,12 @@ lazy_scan_heap(LVRelState *vacrel, VacuumParams *params, bool aggressive) * Periodically perform FSM vacuuming to make newly-freed * space visible on upper FSM pages. Note we have not yet * performed FSM processing for blkno. - * - * Call lazy_check_wraparound_failsafe() here, too, since we - * also don't want to do that too frequently, or too - * infrequently. */ if (blkno - next_fsm_block_to_vacuum >= VACUUM_FSM_EVERY_PAGES) { FreeSpaceMapVacuumRange(vacrel->rel, next_fsm_block_to_vacuum, blkno); next_fsm_block_to_vacuum = blkno; - lazy_check_wraparound_failsafe(vacrel); } /* @@ -2567,22 +2572,13 @@ lazy_check_needs_freeze(Buffer buf, bool *hastup, LVRelState *vacrel) * that it started out with. * * Returns true when failsafe has been triggered. - * - * Caller is expected to call here before and after vacuuming each index in - * the case of two-pass VACUUM, or every VACUUM_FSM_EVERY_PAGES blocks in the - * case of no-indexes/one-pass VACUUM. - * - * There is also a precheck before the first pass over the heap begins, which - * is helpful when the failsafe initially triggers during a non-aggressive - * VACUUM -- the automatic aggressive vacuum to prevent wraparound that - * follows can independently trigger the failsafe right away. */ static bool lazy_check_wraparound_failsafe(LVRelState *vacrel) { /* Avoid calling vacuum_xid_failsafe_check() very frequently */ if (vacrel->num_index_scans == 0 && - vacrel->rel_pages <= FAILSAFE_MIN_PAGES) + vacrel->rel_pages <= FAILSAFE_EVERY_PAGES) return false; /* Don't warn more than once per VACUUM */ @@ -2600,7 +2596,7 @@ lazy_check_wraparound_failsafe(LVRelState *vacrel) vacrel->do_failsafe = true; ereport(WARNING, - (errmsg("abandoned index vacuuming of table \"%s.%s.%s\" as a failsafe after %d index scans", + (errmsg("bypassing nonessential maintenance of table \"%s.%s.%s\" as a failsafe after %d index scans", get_database_name(MyDatabaseId), vacrel->relnamespace, vacrel->relname, -- 2.27.0