diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index 1429ac8b63..95ba3cc401 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -1726,6 +1726,7 @@ _bt_killitems(IndexScanDesc scan)
 	int			numKilled = so->numKilled;
 	bool		killedsomething = false;
 	bool		droppedpin PG_USED_FOR_ASSERTS_ONLY;
+	bool		have_exclusive = false;
 
 	Assert(BTScanPosIsValid(so->currPos));
 
@@ -1767,6 +1768,7 @@ _bt_killitems(IndexScanDesc scan)
 		}
 	}
 
+restart:
 	opaque = (BTPageOpaque) PageGetSpecialPointer(page);
 	minoff = P_FIRSTDATAKEY(opaque);
 	maxoff = PageGetMaxOffsetNumber(page);
@@ -1864,6 +1866,19 @@ _bt_killitems(IndexScanDesc scan)
 			 */
 			if (killtuple && !ItemIdIsDead(iid))
 			{
+				if (!have_exclusive && XLogHintBitIsNeeded())
+				{
+					/*
+					 * If wal_log_hints is enabled, we only want to do this
+					 * with an exclusive lock, so exchange our lock and
+					 * restart from the top.
+					 */
+					LockBuffer(so->currPos.buf, BUFFER_LOCK_UNLOCK);
+					LockBuffer(so->currPos.buf, BT_WRITE);
+					have_exclusive = true;
+					goto restart;
+				}
+
 				/* found the item/all posting list items */
 				ItemIdMarkDead(iid);
 				killedsomething = true;
