@@ -2060,7 +2060,8 @@ heap_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer,
2060
2060
* broken.
2061
2061
*/
2062
2062
if (TransactionIdIsValid (prev_xmax ) &&
2063
- !HeapTupleUpdateXmaxMatchesXmin (prev_xmax , heapTuple -> t_data ))
2063
+ !TransactionIdEquals (prev_xmax ,
2064
+ HeapTupleHeaderGetXmin (heapTuple -> t_data )))
2064
2065
break ;
2065
2066
2066
2067
/*
@@ -2243,7 +2244,7 @@ heap_get_latest_tid(Relation relation,
2243
2244
* tuple. Check for XMIN match.
2244
2245
*/
2245
2246
if (TransactionIdIsValid (priorXmax ) &&
2246
- !HeapTupleUpdateXmaxMatchesXmin (priorXmax , tp .t_data ))
2247
+ !TransactionIdEquals (priorXmax , HeapTupleHeaderGetXmin ( tp .t_data ) ))
2247
2248
{
2248
2249
UnlockReleaseBuffer (buffer );
2249
2250
break ;
@@ -2275,50 +2276,6 @@ heap_get_latest_tid(Relation relation,
2275
2276
} /* end of loop */
2276
2277
}
2277
2278
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
- }
2322
2279
2323
2280
/*
2324
2281
* UpdateXmaxHintBits - update tuple hint bits after xmax transaction ends
@@ -5736,7 +5693,8 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
5736
5693
* end of the chain, we're done, so return success.
5737
5694
*/
5738
5695
if (TransactionIdIsValid (priorXmax ) &&
5739
- !HeapTupleUpdateXmaxMatchesXmin (priorXmax , mytup .t_data ))
5696
+ !TransactionIdEquals (HeapTupleHeaderGetXmin (mytup .t_data ),
5697
+ priorXmax ))
5740
5698
{
5741
5699
result = HeapTupleMayBeUpdated ;
5742
5700
goto out_locked ;
@@ -6430,23 +6388,14 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
6430
6388
Assert (TransactionIdIsValid (xid ));
6431
6389
6432
6390
/*
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.
6440
6393
*/
6441
6394
if (TransactionIdPrecedes (xid , cutoff_xid ))
6442
6395
{
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 */
6450
6399
}
6451
6400
else
6452
6401
{
@@ -6519,16 +6468,13 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
6519
6468
/*
6520
6469
* It's an update; should we keep it? If the transaction is known
6521
6470
* 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.
6522
6474
*
6523
6475
* As with all tuple visibility routines, it's critical to test
6524
6476
* TransactionIdIsInProgress before TransactionIdDidCommit,
6525
6477
* 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.
6532
6478
*/
6533
6479
if (TransactionIdIsCurrentTransactionId (xid ) ||
6534
6480
TransactionIdIsInProgress (xid ))
@@ -6553,6 +6499,13 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
6553
6499
* we can ignore it.
6554
6500
*/
6555
6501
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
+
6556
6509
/*
6557
6510
* If we determined that it's an Xid corresponding to an update
6558
6511
* that must be retained, additionally add it to the list of
@@ -6631,10 +6584,7 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
6631
6584
*
6632
6585
* It is assumed that the caller has checked the tuple with
6633
6586
* 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).
6638
6588
*
6639
6589
* NB: cutoff_xid *must* be <= the current global xmin, to ensure that any
6640
6590
* 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,
6745
6695
else if (TransactionIdIsNormal (xid ))
6746
6696
{
6747
6697
if (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;
6764
6699
else
6765
6700
totally_frozen = false;
6766
6701
}
0 commit comments