From e76a68f196d96f269d5719b46d8ba1c9b8950870 Mon Sep 17 00:00:00 2001
From: Melanie Plageman <melanieplageman@gmail.com>
Date: Wed, 28 Jan 2026 12:51:26 -0500
Subject: [PATCH v34 01/14] Clarify some heap tuple freezing related comments

Some of the comments about calculating the snapshot conflict horizon for
a record freezing tuples needed further elaboration.
---
 src/backend/access/heap/pruneheap.c | 30 +++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)

diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c
index 632c2427952..b9d2b48104c 100644
--- a/src/backend/access/heap/pruneheap.c
+++ b/src/backend/access/heap/pruneheap.c
@@ -736,17 +736,26 @@ heap_page_will_freeze(Relation relation, Buffer buffer,
 		heap_pre_freeze_checks(buffer, prstate->frozen, prstate->nfrozen);
 
 		/*
-		 * Calculate what the snapshot conflict horizon should be for a record
-		 * freezing tuples. We can use the visibility_cutoff_xid as our cutoff
-		 * for conflicts when the whole page is eligible to become all-frozen
-		 * in the VM once we're done with it. Otherwise, we generate a
+		 * Determine the snapshot conflict horizon for freezing tuples on the
+		 * page.
+		 *
+		 * We don't track the newest xmin that will become frozen, so we must
+		 * use a coarser (more conservative) cutoff as the conflict horizon.
+		 *
+		 * We can use the visibility_cutoff_xid as our cutoff for conflicts
+		 * when the whole page is eligible to become all-frozen in the VM once
+		 * we're done with it. Otherwise, we generate an even more
 		 * conservative cutoff by stepping back from OldestXmin.
+		 *
+		 * Ignoring dead items when all other tuples will be frozen allows us
+		 * to pick an older horizon (visibility_cutoff_xid will be older than
+		 * OldestXmin). We will later adjust this horizon to account for dead
+		 * items, moving it forward if the newest removed xid is newer.
 		 */
 		if (prstate->all_frozen)
 			prstate->frz_conflict_horizon = prstate->visibility_cutoff_xid;
 		else
 		{
-			/* Avoids false conflicts when hot_standby_feedback in use */
 			prstate->frz_conflict_horizon = prstate->cutoffs->OldestXmin;
 			TransactionIdRetreat(prstate->frz_conflict_horizon);
 		}
@@ -877,11 +886,12 @@ heap_page_prune_and_freeze(PruneFreezeParams *params,
 	/*
 	 * While scanning the line pointers, we did not clear
 	 * all_visible/all_frozen when encountering LP_DEAD items because we
-	 * wanted the decision whether or not to freeze the page to be unaffected
-	 * by the short-term presence of LP_DEAD items.  These LP_DEAD items are
-	 * effectively assumed to be LP_UNUSED items in the making.  It doesn't
-	 * matter which vacuum heap pass (initial pass or final pass) ends up
-	 * setting the page all-frozen, as long as the ongoing VACUUM does it.
+	 * wanted the decision whether or not to opportunistically freeze the page
+	 * to be unaffected by the short-term presence of LP_DEAD items.  These
+	 * LP_DEAD items are effectively assumed to be LP_UNUSED items in the
+	 * making. It doesn't matter which vacuum heap pass (initial pass or final
+	 * pass) ends up setting the page all-frozen, as long as the ongoing
+	 * VACUUM does it.
 	 *
 	 * Now that we finished determining whether or not to freeze the page,
 	 * update all_visible and all_frozen so that they reflect the true state
-- 
2.43.0

