*** a/src/backend/commands/vacuumlazy.c
--- b/src/backend/commands/vacuumlazy.c
***************
*** 113,118 **** typedef struct LVRelStats
--- 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 */
***************
*** 475,480 **** lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
--- 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);
***************
*** 568,574 **** lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
--- 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;
  		}
  
***************
*** 1559,1568 **** static BlockNumber
--- 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;
***************
*** 1600,1605 **** count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
--- 1615,1622 ----
  									RelationGetRelationName(onerel))));
  
  					vacrelstats->lock_waiter_detected = true;
+ 					if (BufferIsValid(vmbuffer)) 
+ 						ReleaseBuffer(vmbuffer);
  					return blkno;
  				}
  				starttime = currenttime;
***************
*** 1614,1620 **** count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
  		CHECK_FOR_INTERRUPTS();
  
  		blkno--;
! 
  		buf = ReadBufferExtended(onerel, MAIN_FORKNUM, blkno,
  								 RBM_NORMAL, vac_strategy);
  
--- 1631,1644 ----
  		CHECK_FOR_INTERRUPTS();
  
  		blkno--;
! 		
! 		/*
! 		 * Verify the page is empty or not based on visibility map test, instead
! 		 * of verifying from the page contents.
! 		 */
! 		if ((blkno >= trust_vm) && visibilitymap_test(onerel, blkno, &vmbuffer))
! 			continue;
! 		
  		buf = ReadBufferExtended(onerel, MAIN_FORKNUM, blkno,
  								 RBM_NORMAL, vac_strategy);
  
***************
*** 1657,1663 **** count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
--- 1681,1691 ----
  
  		/* Done scanning if we found a tuple here */
  		if (hastup)
+ 		{
+ 			if (BufferIsValid(vmbuffer))
+ 				ReleaseBuffer(vmbuffer);
  			return blkno + 1;
+ 		}
  	}
  
  	/*
***************
*** 1665,1670 **** count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
--- 1693,1700 ----
  	 * pages still are; we need not bother to look at the last known-nonempty
  	 * page.
  	 */
+ 	if (BufferIsValid(vmbuffer))
+ 		ReleaseBuffer(vmbuffer);
  	return vacrelstats->nonempty_pages;
  }
  
