@@ -2060,7 +2060,8 @@ heap_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer,
20602060 * broken.
20612061 */
20622062if (TransactionIdIsValid (prev_xmax )&&
2063- !HeapTupleUpdateXmaxMatchesXmin (prev_xmax ,heapTuple -> t_data ))
2063+ !TransactionIdEquals (prev_xmax ,
2064+ HeapTupleHeaderGetXmin (heapTuple -> t_data )))
20642065break ;
20652066
20662067/*
@@ -2243,7 +2244,7 @@ heap_get_latest_tid(Relation relation,
22432244 * tuple. Check for XMIN match.
22442245 */
22452246if (TransactionIdIsValid (priorXmax )&&
2246- !HeapTupleUpdateXmaxMatchesXmin (priorXmax ,tp .t_data ))
2247+ !TransactionIdEquals (priorXmax ,HeapTupleHeaderGetXmin ( tp .t_data ) ))
22472248{
22482249UnlockReleaseBuffer (buffer );
22492250break ;
@@ -2275,50 +2276,6 @@ heap_get_latest_tid(Relation relation,
22752276}/* end of loop */
22762277}
22772278
2278- /*
2279- * HeapTupleUpdateXmaxMatchesXmin - verify update chain xmax/xmin lineage
2280- *
2281- * Given the new version of a tuple after some update, verify whether the
2282- * given Xmax (corresponding to the previous version) matches the tuple's
2283- * Xmin, taking into account that the Xmin might have been frozen after the
2284- * update.
2285- */
2286- bool
2287- HeapTupleUpdateXmaxMatchesXmin (TransactionId xmax ,HeapTupleHeader htup )
2288- {
2289- TransactionId xmin = HeapTupleHeaderGetXmin (htup );
2290-
2291- /*
2292- * If the xmax of the old tuple is identical to the xmin of the new one,
2293- * it's a match.
2294- */
2295- if (TransactionIdEquals (xmax ,xmin ))
2296- return true;
2297-
2298- /*
2299- * If the Xmin that was in effect prior to a freeze matches the Xmax,
2300- * it's good too.
2301- */
2302- if (HeapTupleHeaderXminFrozen (htup )&&
2303- TransactionIdEquals (HeapTupleHeaderGetRawXmin (htup ),xmax ))
2304- return true;
2305-
2306- /*
2307- * When a tuple is frozen, the original Xmin is lost, but we know it's a
2308- * committed transaction. So unless the Xmax is InvalidXid, we don't know
2309- * for certain that there is a match, but there may be one; and we must
2310- * return true so that a HOT chain that is half-frozen can be walked
2311- * correctly.
2312- *
2313- * We no longer freeze tuples this way, but we must keep this in order to
2314- * interpret pre-pg_upgrade pages correctly.
2315- */
2316- if (TransactionIdEquals (xmin ,FrozenTransactionId )&&
2317- TransactionIdIsValid (xmax ))
2318- return true;
2319-
2320- return false;
2321- }
23222279
23232280/*
23242281 * UpdateXmaxHintBits - update tuple hint bits after xmax transaction ends
@@ -5736,7 +5693,8 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
57365693 * end of the chain, we're done, so return success.
57375694 */
57385695if (TransactionIdIsValid (priorXmax )&&
5739- !HeapTupleUpdateXmaxMatchesXmin (priorXmax ,mytup .t_data ))
5696+ !TransactionIdEquals (HeapTupleHeaderGetXmin (mytup .t_data ),
5697+ priorXmax ))
57405698{
57415699result = HeapTupleMayBeUpdated ;
57425700gotoout_locked ;
@@ -6430,23 +6388,14 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
64306388Assert (TransactionIdIsValid (xid ));
64316389
64326390/*
6433- * The updating transaction cannot possibly be still running, but
6434- * verify whether it has committed, and request to set the
6435- * COMMITTED flag if so. (We normally don't see any tuples in
6436- * this state, because they are removed by page pruning before we
6437- * try to freeze the page; but this can happen if the updating
6438- * transaction commits after the page is pruned but before
6439- * HeapTupleSatisfiesVacuum).
6391+ * If the xid is older than the cutoff, it has to have aborted,
6392+ * otherwise the tuple would have gotten pruned away.
64406393 */
64416394if (TransactionIdPrecedes (xid ,cutoff_xid ))
64426395{
6443- if (TransactionIdDidCommit (xid ))
6444- * flags = FRM_MARK_COMMITTED |FRM_RETURN_IS_XID ;
6445- else
6446- {
6447- * flags |=FRM_INVALIDATE_XMAX ;
6448- xid = InvalidTransactionId ;/* not strictly necessary */
6449- }
6396+ Assert (!TransactionIdDidCommit (xid ));
6397+ * flags |=FRM_INVALIDATE_XMAX ;
6398+ xid = InvalidTransactionId ;/* not strictly necessary */
64506399}
64516400else
64526401{
@@ -6519,16 +6468,13 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
65196468/*
65206469 * It's an update; should we keep it? If the transaction is known
65216470 * aborted or crashed then it's okay to ignore it, otherwise not.
6471+ * Note that an updater older than cutoff_xid cannot possibly be
6472+ * committed, because HeapTupleSatisfiesVacuum would have returned
6473+ * HEAPTUPLE_DEAD and we would not be trying to freeze the tuple.
65226474 *
65236475 * As with all tuple visibility routines, it's critical to test
65246476 * TransactionIdIsInProgress before TransactionIdDidCommit,
65256477 * because of race conditions explained in detail in tqual.c.
6526- *
6527- * We normally don't see committed updating transactions earlier
6528- * than the cutoff xid, because they are removed by page pruning
6529- * before we try to freeze the page; but it can happen if the
6530- * updating transaction commits after the page is pruned but
6531- * before HeapTupleSatisfiesVacuum.
65326478 */
65336479if (TransactionIdIsCurrentTransactionId (xid )||
65346480TransactionIdIsInProgress (xid ))
@@ -6553,6 +6499,13 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
65536499 * we can ignore it.
65546500 */
65556501
6502+ /*
6503+ * Since the tuple wasn't marked HEAPTUPLE_DEAD by vacuum, the
6504+ * update Xid cannot possibly be older than the xid cutoff.
6505+ */
6506+ Assert (!TransactionIdIsValid (update_xid )||
6507+ !TransactionIdPrecedes (update_xid ,cutoff_xid ));
6508+
65566509/*
65576510 * If we determined that it's an Xid corresponding to an update
65586511 * that must be retained, additionally add it to the list of
@@ -6631,10 +6584,7 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
66316584 *
66326585 * It is assumed that the caller has checked the tuple with
66336586 * HeapTupleSatisfiesVacuum() and determined that it is not HEAPTUPLE_DEAD
6634- * (else we should be removing the tuple, not freezing it). However, note
6635- * that we don't remove HOT tuples even if they are dead, and it'd be incorrect
6636- * to freeze them (because that would make them visible), so we mark them as
6637- * update-committed, and needing further freezing later on.
6587+ * (else we should be removing the tuple, not freezing it).
66386588 *
66396589 * NB: cutoff_xid *must* be <= the current global xmin, to ensure that any
66406590 * XID older than it could neither be running nor seen as running by any
@@ -6745,22 +6695,7 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, TransactionId cutoff_xid,
67456695else if (TransactionIdIsNormal (xid ))
67466696{
67476697if (TransactionIdPrecedes (xid ,cutoff_xid ))
6748- {
6749- /*
6750- * Must freeze regular XIDs older than the cutoff. We must not
6751- * freeze a HOT-updated tuple, though; doing so would bring it
6752- * back to life.
6753- */
6754- if (HeapTupleHeaderIsHotUpdated (tuple ))
6755- {
6756- frz -> t_infomask |=HEAP_XMAX_COMMITTED ;
6757- totally_frozen = false;
6758- changed = true;
6759- /* must not freeze */
6760- }
6761- else
6762- freeze_xmax = true;
6763- }
6698+ freeze_xmax = true;
67646699else
67656700totally_frozen = false;
67666701}