@@ -2046,7 +2046,8 @@ heap_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer,
2046
2046
* broken.
2047
2047
*/
2048
2048
if (TransactionIdIsValid (prev_xmax ) &&
2049
- !HeapTupleUpdateXmaxMatchesXmin (prev_xmax , heapTuple -> t_data ))
2049
+ !TransactionIdEquals (prev_xmax ,
2050
+ HeapTupleHeaderGetXmin (heapTuple -> t_data )))
2050
2051
break ;
2051
2052
2052
2053
/*
@@ -2229,7 +2230,7 @@ heap_get_latest_tid(Relation relation,
2229
2230
* tuple. Check for XMIN match.
2230
2231
*/
2231
2232
if (TransactionIdIsValid (priorXmax ) &&
2232
- ! HeapTupleUpdateXmaxMatchesXmin (priorXmax , tp .t_data ))
2233
+ ! TransactionIdEquals (priorXmax , HeapTupleHeaderGetXmin ( tp .t_data ) ))
2233
2234
{
2234
2235
UnlockReleaseBuffer (buffer );
2235
2236
break ;
@@ -2261,50 +2262,6 @@ heap_get_latest_tid(Relation relation,
2261
2262
} /* end of loop */
2262
2263
}
2263
2264
2264
- /*
2265
- * HeapTupleUpdateXmaxMatchesXmin - verify update chain xmax/xmin lineage
2266
- *
2267
- * Given the new version of a tuple after some update, verify whether the
2268
- * given Xmax (corresponding to the previous version) matches the tuple's
2269
- * Xmin, taking into account that the Xmin might have been frozen after the
2270
- * update.
2271
- */
2272
- bool
2273
- HeapTupleUpdateXmaxMatchesXmin (TransactionId xmax , HeapTupleHeader htup )
2274
- {
2275
- TransactionId xmin = HeapTupleHeaderGetXmin (htup );
2276
-
2277
- /*
2278
- * If the xmax of the old tuple is identical to the xmin of the new one,
2279
- * it's a match.
2280
- */
2281
- if (TransactionIdEquals (xmax , xmin ))
2282
- return true;
2283
-
2284
- /*
2285
- * If the Xmin that was in effect prior to a freeze matches the Xmax,
2286
- * it's good too.
2287
- */
2288
- if (HeapTupleHeaderXminFrozen (htup ) &&
2289
- TransactionIdEquals (HeapTupleHeaderGetRawXmin (htup ), xmax ))
2290
- return true;
2291
-
2292
- /*
2293
- * When a tuple is frozen, the original Xmin is lost, but we know it's a
2294
- * committed transaction. So unless the Xmax is InvalidXid, we don't know
2295
- * for certain that there is a match, but there may be one; and we must
2296
- * return true so that a HOT chain that is half-frozen can be walked
2297
- * correctly.
2298
- *
2299
- * We no longer freeze tuples this way, but we must keep this in order to
2300
- * interpret pre-pg_upgrade pages correctly.
2301
- */
2302
- if (TransactionIdEquals (xmin , FrozenTransactionId ) &&
2303
- TransactionIdIsValid (xmax ))
2304
- return true;
2305
-
2306
- return false;
2307
- }
2308
2265
2309
2266
/*
2310
2267
* UpdateXmaxHintBits - update tuple hint bits after xmax transaction ends
@@ -5762,7 +5719,8 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
5762
5719
* end of the chain, we're done, so return success.
5763
5720
*/
5764
5721
if (TransactionIdIsValid (priorXmax ) &&
5765
- !HeapTupleUpdateXmaxMatchesXmin (priorXmax , mytup .t_data ))
5722
+ !TransactionIdEquals (HeapTupleHeaderGetXmin (mytup .t_data ),
5723
+ priorXmax ))
5766
5724
{
5767
5725
result = HeapTupleMayBeUpdated ;
5768
5726
goto out_locked ;
@@ -6456,23 +6414,14 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
6456
6414
Assert (TransactionIdIsValid (xid ));
6457
6415
6458
6416
/*
6459
- * The updating transaction cannot possibly be still running, but
6460
- * verify whether it has committed, and request to set the
6461
- * COMMITTED flag if so. (We normally don't see any tuples in
6462
- * this state, because they are removed by page pruning before we
6463
- * try to freeze the page; but this can happen if the updating
6464
- * transaction commits after the page is pruned but before
6465
- * HeapTupleSatisfiesVacuum).
6417
+ * If the xid is older than the cutoff, it has to have aborted,
6418
+ * otherwise the tuple would have gotten pruned away.
6466
6419
*/
6467
6420
if (TransactionIdPrecedes (xid , cutoff_xid ))
6468
6421
{
6469
- if (TransactionIdDidCommit (xid ))
6470
- * flags = FRM_MARK_COMMITTED | FRM_RETURN_IS_XID ;
6471
- else
6472
- {
6473
- * flags |= FRM_INVALIDATE_XMAX ;
6474
- xid = InvalidTransactionId ; /* not strictly necessary */
6475
- }
6422
+ Assert (!TransactionIdDidCommit (xid ));
6423
+ * flags |= FRM_INVALIDATE_XMAX ;
6424
+ xid = InvalidTransactionId ; /* not strictly necessary */
6476
6425
}
6477
6426
else
6478
6427
{
@@ -6545,16 +6494,13 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
6545
6494
/*
6546
6495
* It's an update; should we keep it? If the transaction is known
6547
6496
* aborted or crashed then it's okay to ignore it, otherwise not.
6497
+ * Note that an updater older than cutoff_xid cannot possibly be
6498
+ * committed, because HeapTupleSatisfiesVacuum would have returned
6499
+ * HEAPTUPLE_DEAD and we would not be trying to freeze the tuple.
6548
6500
*
6549
6501
* As with all tuple visibility routines, it's critical to test
6550
6502
* TransactionIdIsInProgress before TransactionIdDidCommit,
6551
6503
* because of race conditions explained in detail in tqual.c.
6552
- *
6553
- * We normally don't see committed updating transactions earlier
6554
- * than the cutoff xid, because they are removed by page pruning
6555
- * before we try to freeze the page; but it can happen if the
6556
- * updating transaction commits after the page is pruned but
6557
- * before HeapTupleSatisfiesVacuum.
6558
6504
*/
6559
6505
if (TransactionIdIsCurrentTransactionId (xid ) ||
6560
6506
TransactionIdIsInProgress (xid ))
@@ -6579,6 +6525,13 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
6579
6525
* we can ignore it.
6580
6526
*/
6581
6527
6528
+ /*
6529
+ * Since the tuple wasn't marked HEAPTUPLE_DEAD by vacuum, the
6530
+ * update Xid cannot possibly be older than the xid cutoff.
6531
+ */
6532
+ Assert (!TransactionIdIsValid (update_xid ) ||
6533
+ !TransactionIdPrecedes (update_xid , cutoff_xid ));
6534
+
6582
6535
/*
6583
6536
* If we determined that it's an Xid corresponding to an update
6584
6537
* that must be retained, additionally add it to the list of
@@ -6657,10 +6610,7 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
6657
6610
*
6658
6611
* It is assumed that the caller has checked the tuple with
6659
6612
* HeapTupleSatisfiesVacuum() and determined that it is not HEAPTUPLE_DEAD
6660
- * (else we should be removing the tuple, not freezing it). However, note
6661
- * that we don't remove HOT tuples even if they are dead, and it'd be incorrect
6662
- * to freeze them (because that would make them visible), so we mark them as
6663
- * update-committed, and needing further freezing later on.
6613
+ * (else we should be removing the tuple, not freezing it).
6664
6614
*
6665
6615
* NB: cutoff_xid *must* be <= the current global xmin, to ensure that any
6666
6616
* XID older than it could neither be running nor seen as running by any
@@ -6771,22 +6721,7 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, TransactionId cutoff_xid,
6771
6721
else if (TransactionIdIsNormal (xid ))
6772
6722
{
6773
6723
if (TransactionIdPrecedes (xid , cutoff_xid ))
6774
- {
6775
- /*
6776
- * Must freeze regular XIDs older than the cutoff. We must not
6777
- * freeze a HOT-updated tuple, though; doing so would bring it
6778
- * back to life.
6779
- */
6780
- if (HeapTupleHeaderIsHotUpdated (tuple ))
6781
- {
6782
- frz -> t_infomask |= HEAP_XMAX_COMMITTED ;
6783
- totally_frozen = false;
6784
- changed = true;
6785
- /* must not freeze */
6786
- }
6787
- else
6788
- freeze_xmax = true;
6789
- }
6724
+ freeze_xmax = true;
6790
6725
else
6791
6726
totally_frozen = false;
6792
6727
}
0 commit comments