From dd38d0152b7d0044eb8a82e6aa27239a8c071da2 Mon Sep 17 00:00:00 2001 From: Melanie Plageman Date: Mon, 13 Nov 2023 16:47:08 -0500 Subject: [PATCH v1 2/3] Indicate rel truncation unsafe in lazy_scan[no]prune Both lazy_scan_prune() and lazy_scan_noprune() must determine whether or not there are tuples on the page making rel truncation unsafe. LVRelState->nonempty_pages is updated to reflect this. Previously, both functions set an output parameter or output parameter member, hastup, to indicate that nonempty_pages should be updated to reflect the latest non-removable page. There doesn't seem to be any reason to wait until lazy_scan_[no]prune() returns to update nonempty_pages. Plenty of other counters in the LVRelState are updated in lazy_scan_[no]prune(). This allows us to get rid of the output parameter hastup. --- src/backend/access/heap/vacuumlazy.c | 50 +++++++++++++++------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 8b729828ce..379f693280 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -217,7 +217,6 @@ typedef struct LVRelState */ typedef struct LVPagePruneState { - bool hastup; /* Page prevents rel truncation? */ bool has_lpdead_items; /* includes existing LP_DEAD items */ /* @@ -253,7 +252,7 @@ static void lazy_scan_prune(LVRelState *vacrel, Buffer buf, LVPagePruneState *prunestate); static bool lazy_scan_noprune(LVRelState *vacrel, Buffer buf, BlockNumber blkno, Page page, - bool *hastup, bool *recordfreespace); + bool *recordfreespace); static void lazy_vacuum(LVRelState *vacrel); static bool lazy_vacuum_all_indexes(LVRelState *vacrel); static void lazy_vacuum_heap_rel(LVRelState *vacrel); @@ -959,8 +958,7 @@ lazy_scan_heap(LVRelState *vacrel) page = BufferGetPage(buf); if (!ConditionalLockBufferForCleanup(buf)) { - bool hastup, - recordfreespace; + bool recordfreespace; LockBuffer(buf, BUFFER_LOCK_SHARE); @@ -972,20 +970,21 @@ lazy_scan_heap(LVRelState *vacrel) continue; } - /* Collect LP_DEAD items in dead_items array, count tuples */ - if (lazy_scan_noprune(vacrel, buf, blkno, page, &hastup, + /* + * Collect LP_DEAD items in dead_items array, count tuples, + * determine if rel truncation is safe + */ + if (lazy_scan_noprune(vacrel, buf, blkno, page, &recordfreespace)) { Size freespace = 0; /* * Processed page successfully (without cleanup lock) -- just - * need to perform rel truncation and FSM steps, much like the - * lazy_scan_prune case. Don't bother trying to match its - * visibility map setting steps, though. + * need to update the FSM, much like the lazy_scan_prune case. + * Don't bother trying to match its visibility map setting + * steps, though. */ - if (hastup) - vacrel->nonempty_pages = blkno + 1; if (recordfreespace) freespace = PageGetHeapFreeSpace(page); UnlockReleaseBuffer(buf); @@ -1023,10 +1022,6 @@ lazy_scan_heap(LVRelState *vacrel) Assert(!prunestate.all_visible || !prunestate.has_lpdead_items); - /* Remember the location of the last page with nonremovable tuples */ - if (prunestate.hastup) - vacrel->nonempty_pages = blkno + 1; - if (vacrel->nindexes == 0) { /* @@ -1549,6 +1544,7 @@ lazy_scan_prune(LVRelState *vacrel, live_tuples, recently_dead_tuples; HeapPageFreeze pagefrz; + bool hastup = false; int64 fpi_before = pgWalUsage.wal_fpi; OffsetNumber deadoffsets[MaxHeapTuplesPerPage]; HeapTupleFreeze frozen[MaxHeapTuplesPerPage]; @@ -1587,7 +1583,6 @@ lazy_scan_prune(LVRelState *vacrel, * Now scan the page to collect LP_DEAD items and check for tuples * requiring freezing among remaining tuples with storage */ - prunestate->hastup = false; prunestate->has_lpdead_items = false; prunestate->all_visible = true; prunestate->all_frozen = true; @@ -1614,7 +1609,7 @@ lazy_scan_prune(LVRelState *vacrel, if (ItemIdIsRedirected(itemid)) { /* page makes rel truncation unsafe */ - prunestate->hastup = true; + hastup = true; continue; } @@ -1744,7 +1739,7 @@ lazy_scan_prune(LVRelState *vacrel, break; } - prunestate->hastup = true; /* page makes rel truncation unsafe */ + hastup = true; /* page makes rel truncation unsafe */ /* Tuple with storage -- consider need to freeze */ if (heap_prepare_freeze_tuple(htup, &vacrel->cutoffs, &pagefrz, @@ -1912,6 +1907,10 @@ lazy_scan_prune(LVRelState *vacrel, vacrel->lpdead_items += lpdead_items; vacrel->live_tuples += live_tuples; vacrel->recently_dead_tuples += recently_dead_tuples; + + /* Remember the location of the last page with nonremovable tuples */ + if (hastup) + vacrel->nonempty_pages = blkno + 1; } /* @@ -1929,7 +1928,6 @@ lazy_scan_prune(LVRelState *vacrel, * one or more tuples on the page. We always return true for non-aggressive * callers. * - * See lazy_scan_prune for an explanation of hastup return flag. * recordfreespace flag instructs caller on whether or not it should do * generic FSM processing for page. */ @@ -1938,7 +1936,6 @@ lazy_scan_noprune(LVRelState *vacrel, Buffer buf, BlockNumber blkno, Page page, - bool *hastup, bool *recordfreespace) { OffsetNumber offnum, @@ -1947,6 +1944,7 @@ lazy_scan_noprune(LVRelState *vacrel, live_tuples, recently_dead_tuples, missed_dead_tuples; + bool hastup; HeapTupleHeader tupleheader; TransactionId NoFreezePageRelfrozenXid = vacrel->NewRelfrozenXid; MultiXactId NoFreezePageRelminMxid = vacrel->NewRelminMxid; @@ -1954,7 +1952,7 @@ lazy_scan_noprune(LVRelState *vacrel, Assert(BufferGetBlockNumber(buf) == blkno); - *hastup = false; /* for now */ + hastup = false; /* for now */ *recordfreespace = false; /* for now */ lpdead_items = 0; @@ -1978,7 +1976,7 @@ lazy_scan_noprune(LVRelState *vacrel, if (ItemIdIsRedirected(itemid)) { - *hastup = true; + hastup = true; continue; } @@ -1992,7 +1990,7 @@ lazy_scan_noprune(LVRelState *vacrel, continue; } - *hastup = true; /* page prevents rel truncation */ + hastup = true; /* page prevents rel truncation */ tupleheader = (HeapTupleHeader) PageGetItem(page, itemid); if (heap_tuple_should_freeze(tupleheader, &vacrel->cutoffs, &NoFreezePageRelfrozenXid, @@ -2094,7 +2092,7 @@ lazy_scan_noprune(LVRelState *vacrel, * but it beats having to maintain specialized heap vacuuming code * forever, for vanishingly little benefit.) */ - *hastup = true; + hastup = true; missed_dead_tuples += lpdead_items; } @@ -2150,6 +2148,10 @@ lazy_scan_noprune(LVRelState *vacrel, if (missed_dead_tuples > 0) vacrel->missed_dead_pages++; + /* rel truncation is unsafe */ + if (hastup) + vacrel->nonempty_pages = blkno + 1; + /* Caller won't need to call lazy_scan_prune with same page */ return true; } -- 2.37.2