From 54dbd9cbe68cbe7f9aa2a7c4d8f262b15410d3e6 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Fri, 18 Sep 2026 15:45:03 -0400
Subject: [PATCH 4/4] Retain newest live xid as prune hint after visibility
 horizon rejection

When a page contains committed live tuples that are not yet visible to
all snapshots, pruning cannot mark it all-visible. These tuples do not
contribute to new_prune_xid, so pruning can clear pd_prune_xid and
prevent subsequent on-access scans from reconsidering the page after the
horizon advances. Vacuum scans the page regardless of pd_prune_xid, so
the only change to its behavior is that it may dirty the page to set
pd_prune_xid when it otherwise wouldn't have.

Record the newest live xmin as a retry hint when the visibility horizon
prevents setting the VM. Preserve any earlier pruning opportunity already
recorded so that dead tuples can still be reclaimed sooner.
---
 src/backend/access/heap/pruneheap.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c
index 07ef563b874..4c8ddc4f743 100644
--- a/src/backend/access/heap/pruneheap.c
+++ b/src/backend/access/heap/pruneheap.c
@@ -1209,8 +1209,20 @@ heap_page_prune_and_freeze(PruneFreezeParams *params,
 		GlobalVisTestXidConsideredRunning(prstate.vistest,
 										  prstate.newest_live_xid,
 										  true))
+	{
 		prstate.set_all_visible = prstate.set_all_frozen = false;
 
+		/*
+		 * Preserve an opportunity to set the VM on-access once the newest
+		 * live xmin is visible to everyone. Retain any earlier pruning
+		 * opportunity already recorded, so that we can still reclaim dead
+		 * tuples sooner.
+		 */
+		if (!TransactionIdIsValid(prstate.new_prune_xid) ||
+			TransactionIdPrecedes(prstate.newest_live_xid, prstate.new_prune_xid))
+			prstate.new_prune_xid = prstate.newest_live_xid;
+	}
+
 	/*
 	 * If checksums are enabled, calling heap_prune_satisfies_vacuum() while
 	 * checking tuple visibility information in prune_freeze_plan() may have
-- 
2.43.0

