On Mon, Jun 2, 2025 at 2:50 PM Melanie Plageman <melanieplage...@gmail.com> wrote: > As you've explained, it will always be <= OldestXmin. And, if the > record only freezes tuples (meaning it makes no other changes to the > page) and all of those tuples' xmins were considered when calculating > prunestate->visibility_cutoff_xid, then, even if the page isn't > all-frozen, how could it be incorrect to use the > prunestate->visibility_cutoff_xid as the horizon?
Obviously, it isn't safe to use prunestate->visibility_cutoff_xid unless it has actually been maintained using all of the tuples on the page. It is primarily intended for use by the VM record (though it doesn't have to continue to work that way, of course). > Why do we use > OldestXmin when the page wouldn't be all-frozen? It has always worked that way (except that it was FreezeLimit, not OldestXmin, since we could only ever freeze precisely those tuples < FreezeLimit before Postgres 16). Using prunestate->visibility_cutoff_xid instead (when that was possible) was a big improvement. You're right that in principle we could safely use a conflict horizon XID before OldestXmin in cases where we still give up and just use OldestXmin (cases where we just use "OldestXmin - 1", I should say). I'm not sure how much this matters in practice; I imagine that using prunestate->visibility_cutoff_xid is very much the common case with page-level freezing. -- Peter Geoghegan