diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c index 02f3cf3..f0d054a 100644 --- a/src/backend/commands/vacuumlazy.c +++ b/src/backend/commands/vacuumlazy.c @@ -1052,15 +1052,15 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats, static void lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) { - int tupindex; - int npages; + int tupindex = 0; + int npages = 0; + int ntupskipped = 0; + int npagesskipped = 0; PGRUsage ru0; Buffer vmbuffer = InvalidBuffer; pg_rusage_init(&ru0); - npages = 0; - tupindex = 0; while (tupindex < vacrelstats->num_dead_tuples) { BlockNumber tblk; @@ -1075,9 +1075,32 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) vac_strategy); if (!ConditionalLockBufferForCleanup(buf)) { - ReleaseBuffer(buf); - ++tupindex; - continue; + /* + * If we can't get the lock, sleep, then try again just once. + * + * If we can't get the lock the second time, skip this block and + * move onto the next one. This is possible because by now we + * know the tuples are dead and all index pointers to them have been + * removed, so it is safe to ignore them, even if not ideal. + */ + VacuumCostBalance += VacuumCostLimit; + vacuum_delay_point(); + if (!ConditionalLockBufferForCleanup(buf)) + { + BlockNumber blkno = tblk; + + ReleaseBuffer(buf); + tupindex++; + for (; tupindex < vacrelstats->num_dead_tuples; tupindex++) + { + ntupskipped++; + tblk = ItemPointerGetBlockNumber(&vacrelstats->dead_tuples[tupindex]); + if (tblk != blkno) + break; + } + npagesskipped++; + continue; + } } tupindex = lazy_vacuum_page(onerel, tblk, buf, tupindex, vacrelstats, &vmbuffer); @@ -1098,9 +1121,9 @@ lazy_vacuum_heap(Relation onerel, LVRelStats *vacrelstats) } ereport(elevel, - (errmsg("\"%s\": removed %d row versions in %d pages", + (errmsg("\"%s\": removed %d row versions in %d pages (skipped %d row versions in %d pages)", RelationGetRelationName(onerel), - tupindex, npages), + tupindex - ntupskipped, npages, ntupskipped, npagesskipped), errdetail("%s.", pg_rusage_show(&ru0)))); }