diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c new file mode 100644 index a01cfb4..d2cce18 *** a/src/backend/commands/vacuumlazy.c --- b/src/backend/commands/vacuumlazy.c *************** typedef struct LVRelStats *** 113,118 **** --- 113,119 ---- BlockNumber pages_removed; double tuples_deleted; BlockNumber nonempty_pages; /* actually, last nonempty page + 1 */ + BlockNumber skipped_pages; /* actually, last skipped page + 1 */ /* List of TIDs of tuples we intend to delete */ /* NB: this list is ordered by TID address */ int num_dead_tuples; /* current # of entries */ *************** lazy_scan_heap(Relation onerel, LVRelSta *** 475,480 **** --- 476,482 ---- vacrelstats->rel_pages = nblocks; vacrelstats->scanned_pages = 0; vacrelstats->nonempty_pages = 0; + vacrelstats->skipped_pages = 0; vacrelstats->latestRemovedXid = InvalidTransactionId; lazy_space_alloc(vacrelstats, nblocks); *************** lazy_scan_heap(Relation onerel, LVRelSta *** 568,574 **** --- 570,579 ---- { /* Current block is all-visible */ if (skipping_all_visible_blocks && !scan_all) + { + vacrelstats->skipped_pages = blkno + 1; continue; + } all_visible_according_to_vm = true; } *************** static BlockNumber *** 1559,1568 **** --- 1564,1583 ---- count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats) { BlockNumber blkno; + BlockNumber trust_vm; instr_time starttime; + Buffer vmbuffer = InvalidBuffer; /* Initialize the starttime if we check for conflicting lock requests */ INSTR_TIME_SET_CURRENT(starttime); + + /* + * Pages that were inspected and found to be empty by this vacuum run + * must still be empty if the vm bit is still set. Only vacuum sets + * vm bits, and only one vacuum can exist in a table at one time. + */ + trust_vm=vacrelstats->nonempty_pages>vacrelstats->skipped_pages ? + vacrelstats->nonempty_pages : vacrelstats->skipped_pages; /* Strange coding of loop control is needed because blkno is unsigned */ blkno = vacrelstats->rel_pages; *************** count_nondeletable_pages(Relation onerel *** 1600,1605 **** --- 1615,1622 ---- RelationGetRelationName(onerel)))); vacrelstats->lock_waiter_detected = true; + if (BufferIsValid(vmbuffer)) + ReleaseBuffer(vmbuffer); return blkno; } starttime = currenttime; *************** count_nondeletable_pages(Relation onerel *** 1615,1620 **** --- 1632,1648 ---- blkno--; + if (blkno >= trust_vm) + { + if (!visibilitymap_test(onerel,blkno,&vmbuffer)) + { + if (BufferIsValid(vmbuffer)) + ReleaseBuffer(vmbuffer); + return blkno + 1; + } + continue; + } + buf = ReadBufferExtended(onerel, MAIN_FORKNUM, blkno, RBM_NORMAL, vac_strategy); *************** count_nondeletable_pages(Relation onerel *** 1657,1663 **** --- 1685,1695 ---- /* Done scanning if we found a tuple here */ if (hastup) + { + if (BufferIsValid(vmbuffer)) + ReleaseBuffer(vmbuffer); return blkno + 1; + } } /* *************** count_nondeletable_pages(Relation onerel *** 1665,1670 **** --- 1697,1704 ---- * pages still are; we need not bother to look at the last known-nonempty * page. */ + if (BufferIsValid(vmbuffer)) + ReleaseBuffer(vmbuffer); return vacrelstats->nonempty_pages; }