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))));
 }
