@@ -2074,7 +2074,8 @@ heap_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer,
20742074 * broken.
20752075 */
20762076 if (TransactionIdIsValid (prev_xmax ) &&
2077- !HeapTupleUpdateXmaxMatchesXmin (prev_xmax , heapTuple -> t_data ))
2077+ !TransactionIdEquals (prev_xmax ,
2078+ HeapTupleHeaderGetXmin (heapTuple -> t_data )))
20782079 break ;
20792080
20802081 /*
@@ -2260,7 +2261,7 @@ heap_get_latest_tid(Relation relation,
22602261 * tuple. Check for XMIN match.
22612262 */
22622263 if (TransactionIdIsValid (priorXmax ) &&
2263- !HeapTupleUpdateXmaxMatchesXmin (priorXmax , tp .t_data ))
2264+ !TransactionIdEquals (priorXmax , HeapTupleHeaderGetXmin ( tp .t_data ) ))
22642265 {
22652266 UnlockReleaseBuffer (buffer );
22662267 break ;
@@ -2292,50 +2293,6 @@ heap_get_latest_tid(Relation relation,
22922293 } /* end of loop */
22932294}
22942295
2295- /*
2296- * HeapTupleUpdateXmaxMatchesXmin - verify update chain xmax/xmin lineage
2297- *
2298- * Given the new version of a tuple after some update, verify whether the
2299- * given Xmax (corresponding to the previous version) matches the tuple's
2300- * Xmin, taking into account that the Xmin might have been frozen after the
2301- * update.
2302- */
2303- bool
2304- HeapTupleUpdateXmaxMatchesXmin (TransactionId xmax , HeapTupleHeader htup )
2305- {
2306- TransactionId xmin = HeapTupleHeaderGetXmin (htup );
2307-
2308- /*
2309- * If the xmax of the old tuple is identical to the xmin of the new one,
2310- * it's a match.
2311- */
2312- if (TransactionIdEquals (xmax , xmin ))
2313- return true;
2314-
2315- /*
2316- * If the Xmin that was in effect prior to a freeze matches the Xmax,
2317- * it's good too.
2318- */
2319- if (HeapTupleHeaderXminFrozen (htup ) &&
2320- TransactionIdEquals (HeapTupleHeaderGetRawXmin (htup ), xmax ))
2321- return true;
2322-
2323- /*
2324- * When a tuple is frozen, the original Xmin is lost, but we know it's a
2325- * committed transaction. So unless the Xmax is InvalidXid, we don't know
2326- * for certain that there is a match, but there may be one; and we must
2327- * return true so that a HOT chain that is half-frozen can be walked
2328- * correctly.
2329- *
2330- * We no longer freeze tuples this way, but we must keep this in order to
2331- * interpret pre-pg_upgrade pages correctly.
2332- */
2333- if (TransactionIdEquals (xmin , FrozenTransactionId ) &&
2334- TransactionIdIsValid (xmax ))
2335- return true;
2336-
2337- return false;
2338- }
23392296
23402297/*
23412298 * UpdateXmaxHintBits - update tuple hint bits after xmax transaction ends
@@ -5755,7 +5712,8 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
57555712 * end of the chain, we're done, so return success.
57565713 */
57575714 if (TransactionIdIsValid (priorXmax ) &&
5758- !HeapTupleUpdateXmaxMatchesXmin (priorXmax , mytup .t_data ))
5715+ !TransactionIdEquals (HeapTupleHeaderGetXmin (mytup .t_data ),
5716+ priorXmax ))
57595717 {
57605718 result = HeapTupleMayBeUpdated ;
57615719 goto out_locked ;
@@ -6449,23 +6407,14 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
64496407 Assert (TransactionIdIsValid (xid ));
64506408
64516409 /*
6452- * The updating transaction cannot possibly be still running, but
6453- * verify whether it has committed, and request to set the
6454- * COMMITTED flag if so. (We normally don't see any tuples in
6455- * this state, because they are removed by page pruning before we
6456- * try to freeze the page; but this can happen if the updating
6457- * transaction commits after the page is pruned but before
6458- * HeapTupleSatisfiesVacuum).
6410+ * If the xid is older than the cutoff, it has to have aborted,
6411+ * otherwise the tuple would have gotten pruned away.
64596412 */
64606413 if (TransactionIdPrecedes (xid , cutoff_xid ))
64616414 {
6462- if (TransactionIdDidCommit (xid ))
6463- * flags = FRM_MARK_COMMITTED | FRM_RETURN_IS_XID ;
6464- else
6465- {
6466- * flags |= FRM_INVALIDATE_XMAX ;
6467- xid = InvalidTransactionId ; /* not strictly necessary */
6468- }
6415+ Assert (!TransactionIdDidCommit (xid ));
6416+ * flags |= FRM_INVALIDATE_XMAX ;
6417+ xid = InvalidTransactionId ; /* not strictly necessary */
64696418 }
64706419 else
64716420 {
@@ -6538,16 +6487,13 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
65386487 /*
65396488 * It's an update; should we keep it? If the transaction is known
65406489 * aborted or crashed then it's okay to ignore it, otherwise not.
6490+ * Note that an updater older than cutoff_xid cannot possibly be
6491+ * committed, because HeapTupleSatisfiesVacuum would have returned
6492+ * HEAPTUPLE_DEAD and we would not be trying to freeze the tuple.
65416493 *
65426494 * As with all tuple visibility routines, it's critical to test
65436495 * TransactionIdIsInProgress before TransactionIdDidCommit,
65446496 * because of race conditions explained in detail in tqual.c.
6545- *
6546- * We normally don't see committed updating transactions earlier
6547- * than the cutoff xid, because they are removed by page pruning
6548- * before we try to freeze the page; but it can happen if the
6549- * updating transaction commits after the page is pruned but
6550- * before HeapTupleSatisfiesVacuum.
65516497 */
65526498 if (TransactionIdIsCurrentTransactionId (xid ) ||
65536499 TransactionIdIsInProgress (xid ))
@@ -6572,6 +6518,13 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
65726518 * we can ignore it.
65736519 */
65746520
6521+ /*
6522+ * Since the tuple wasn't marked HEAPTUPLE_DEAD by vacuum, the
6523+ * update Xid cannot possibly be older than the xid cutoff.
6524+ */
6525+ Assert (!TransactionIdIsValid (update_xid ) ||
6526+ !TransactionIdPrecedes (update_xid , cutoff_xid ));
6527+
65756528 /*
65766529 * If we determined that it's an Xid corresponding to an update
65776530 * that must be retained, additionally add it to the list of
@@ -6650,10 +6603,7 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
66506603 *
66516604 * It is assumed that the caller has checked the tuple with
66526605 * HeapTupleSatisfiesVacuum() and determined that it is not HEAPTUPLE_DEAD
6653- * (else we should be removing the tuple, not freezing it). However, note
6654- * that we don't remove HOT tuples even if they are dead, and it'd be incorrect
6655- * to freeze them (because that would make them visible), so we mark them as
6656- * update-committed, and needing further freezing later on.
6606+ * (else we should be removing the tuple, not freezing it).
66576607 *
66586608 * NB: cutoff_xid *must* be <= the current global xmin, to ensure that any
66596609 * XID older than it could neither be running nor seen as running by any
@@ -6764,22 +6714,7 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, TransactionId cutoff_xid,
67646714 else if (TransactionIdIsNormal (xid ))
67656715 {
67666716 if (TransactionIdPrecedes (xid , cutoff_xid ))
6767- {
6768- /*
6769- * Must freeze regular XIDs older than the cutoff. We must not
6770- * freeze a HOT-updated tuple, though; doing so would bring it
6771- * back to life.
6772- */
6773- if (HeapTupleHeaderIsHotUpdated (tuple ))
6774- {
6775- frz -> t_infomask |= HEAP_XMAX_COMMITTED ;
6776- totally_frozen = false;
6777- changed = true;
6778- /* must not freeze */
6779- }
6780- else
6781- freeze_xmax = true;
6782- }
6717+ freeze_xmax = true;
67836718 else
67846719 totally_frozen = false;
67856720 }
0 commit comments