@@ -2074,7 +2074,8 @@ heap_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer,
2074
2074
* broken.
2075
2075
*/
2076
2076
if (TransactionIdIsValid (prev_xmax ) &&
2077
- !HeapTupleUpdateXmaxMatchesXmin (prev_xmax , heapTuple -> t_data ))
2077
+ !TransactionIdEquals (prev_xmax ,
2078
+ HeapTupleHeaderGetXmin (heapTuple -> t_data )))
2078
2079
break ;
2079
2080
2080
2081
/*
@@ -2260,7 +2261,7 @@ heap_get_latest_tid(Relation relation,
2260
2261
* tuple. Check for XMIN match.
2261
2262
*/
2262
2263
if (TransactionIdIsValid (priorXmax ) &&
2263
- !HeapTupleUpdateXmaxMatchesXmin (priorXmax , tp .t_data ))
2264
+ !TransactionIdEquals (priorXmax , HeapTupleHeaderGetXmin ( tp .t_data ) ))
2264
2265
{
2265
2266
UnlockReleaseBuffer (buffer );
2266
2267
break ;
@@ -2292,50 +2293,6 @@ heap_get_latest_tid(Relation relation,
2292
2293
} /* end of loop */
2293
2294
}
2294
2295
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
- }
2339
2296
2340
2297
/*
2341
2298
* UpdateXmaxHintBits - update tuple hint bits after xmax transaction ends
@@ -5755,7 +5712,8 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
5755
5712
* end of the chain, we're done, so return success.
5756
5713
*/
5757
5714
if (TransactionIdIsValid (priorXmax ) &&
5758
- !HeapTupleUpdateXmaxMatchesXmin (priorXmax , mytup .t_data ))
5715
+ !TransactionIdEquals (HeapTupleHeaderGetXmin (mytup .t_data ),
5716
+ priorXmax ))
5759
5717
{
5760
5718
result = HeapTupleMayBeUpdated ;
5761
5719
goto out_locked ;
@@ -6449,23 +6407,14 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
6449
6407
Assert (TransactionIdIsValid (xid ));
6450
6408
6451
6409
/*
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.
6459
6412
*/
6460
6413
if (TransactionIdPrecedes (xid , cutoff_xid ))
6461
6414
{
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 */
6469
6418
}
6470
6419
else
6471
6420
{
@@ -6538,16 +6487,13 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
6538
6487
/*
6539
6488
* It's an update; should we keep it? If the transaction is known
6540
6489
* 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.
6541
6493
*
6542
6494
* As with all tuple visibility routines, it's critical to test
6543
6495
* TransactionIdIsInProgress before TransactionIdDidCommit,
6544
6496
* 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.
6551
6497
*/
6552
6498
if (TransactionIdIsCurrentTransactionId (xid ) ||
6553
6499
TransactionIdIsInProgress (xid ))
@@ -6572,6 +6518,13 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
6572
6518
* we can ignore it.
6573
6519
*/
6574
6520
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
+
6575
6528
/*
6576
6529
* If we determined that it's an Xid corresponding to an update
6577
6530
* that must be retained, additionally add it to the list of
@@ -6650,10 +6603,7 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
6650
6603
*
6651
6604
* It is assumed that the caller has checked the tuple with
6652
6605
* 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).
6657
6607
*
6658
6608
* NB: cutoff_xid *must* be <= the current global xmin, to ensure that any
6659
6609
* 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,
6764
6714
else if (TransactionIdIsNormal (xid ))
6765
6715
{
6766
6716
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;
6783
6718
else
6784
6719
totally_frozen = false;
6785
6720
}
0 commit comments