@@ -1824,7 +1824,8 @@ heap_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer,
1824
1824
* broken.
1825
1825
*/
1826
1826
if (TransactionIdIsValid (prev_xmax ) &&
1827
- !HeapTupleUpdateXmaxMatchesXmin (prev_xmax , heapTuple -> t_data ))
1827
+ !TransactionIdEquals (prev_xmax ,
1828
+ HeapTupleHeaderGetXmin (heapTuple -> t_data )))
1828
1829
break ;
1829
1830
1830
1831
/*
@@ -2006,7 +2007,7 @@ heap_get_latest_tid(Relation relation,
2006
2007
* tuple. Check for XMIN match.
2007
2008
*/
2008
2009
if (TransactionIdIsValid (priorXmax ) &&
2009
- ! HeapTupleUpdateXmaxMatchesXmin (priorXmax , tp .t_data ))
2010
+ ! TransactionIdEquals (priorXmax , HeapTupleHeaderGetXmin ( tp .t_data ) ))
2010
2011
{
2011
2012
UnlockReleaseBuffer (buffer );
2012
2013
break ;
@@ -2038,50 +2039,6 @@ heap_get_latest_tid(Relation relation,
2038
2039
} /* end of loop */
2039
2040
}
2040
2041
2041
- /*
2042
- * HeapTupleUpdateXmaxMatchesXmin - verify update chain xmax/xmin lineage
2043
- *
2044
- * Given the new version of a tuple after some update, verify whether the
2045
- * given Xmax (corresponding to the previous version) matches the tuple's
2046
- * Xmin, taking into account that the Xmin might have been frozen after the
2047
- * update.
2048
- */
2049
- bool
2050
- HeapTupleUpdateXmaxMatchesXmin (TransactionId xmax , HeapTupleHeader htup )
2051
- {
2052
- TransactionId xmin = HeapTupleHeaderGetXmin (htup );
2053
-
2054
- /*
2055
- * If the xmax of the old tuple is identical to the xmin of the new one,
2056
- * it's a match.
2057
- */
2058
- if (TransactionIdEquals (xmax , xmin ))
2059
- return true;
2060
-
2061
- /*
2062
- * If the Xmin that was in effect prior to a freeze matches the Xmax,
2063
- * it's good too.
2064
- */
2065
- if (HeapTupleHeaderXminFrozen (htup ) &&
2066
- TransactionIdEquals (HeapTupleHeaderGetRawXmin (htup ), xmax ))
2067
- return true;
2068
-
2069
- /*
2070
- * When a tuple is frozen, the original Xmin is lost, but we know it's a
2071
- * committed transaction. So unless the Xmax is InvalidXid, we don't know
2072
- * for certain that there is a match, but there may be one; and we must
2073
- * return true so that a HOT chain that is half-frozen can be walked
2074
- * correctly.
2075
- *
2076
- * We no longer freeze tuples this way, but we must keep this in order to
2077
- * interpret pre-pg_upgrade pages correctly.
2078
- */
2079
- if (TransactionIdEquals (xmin , FrozenTransactionId ) &&
2080
- TransactionIdIsValid (xmax ))
2081
- return true;
2082
-
2083
- return false;
2084
- }
2085
2042
2086
2043
/*
2087
2044
* UpdateXmaxHintBits - update tuple hint bits after xmax transaction ends
@@ -5443,7 +5400,8 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
5443
5400
* end of the chain, we're done, so return success.
5444
5401
*/
5445
5402
if (TransactionIdIsValid (priorXmax ) &&
5446
- !HeapTupleUpdateXmaxMatchesXmin (priorXmax , mytup .t_data ))
5403
+ !TransactionIdEquals (HeapTupleHeaderGetXmin (mytup .t_data ),
5404
+ priorXmax ))
5447
5405
{
5448
5406
UnlockReleaseBuffer (buf );
5449
5407
return HeapTupleMayBeUpdated ;
@@ -6122,23 +6080,14 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
6122
6080
Assert (TransactionIdIsValid (xid ));
6123
6081
6124
6082
/*
6125
- * The updating transaction cannot possibly be still running, but
6126
- * verify whether it has committed, and request to set the
6127
- * COMMITTED flag if so. (We normally don't see any tuples in
6128
- * this state, because they are removed by page pruning before we
6129
- * try to freeze the page; but this can happen if the updating
6130
- * transaction commits after the page is pruned but before
6131
- * HeapTupleSatisfiesVacuum).
6083
+ * If the xid is older than the cutoff, it has to have aborted,
6084
+ * otherwise the tuple would have gotten pruned away.
6132
6085
*/
6133
6086
if (TransactionIdPrecedes (xid , cutoff_xid ))
6134
6087
{
6135
- if (TransactionIdDidCommit (xid ))
6136
- * flags = FRM_MARK_COMMITTED | FRM_RETURN_IS_XID ;
6137
- else
6138
- {
6139
- * flags |= FRM_INVALIDATE_XMAX ;
6140
- xid = InvalidTransactionId ; /* not strictly necessary */
6141
- }
6088
+ Assert (!TransactionIdDidCommit (xid ));
6089
+ * flags |= FRM_INVALIDATE_XMAX ;
6090
+ xid = InvalidTransactionId ; /* not strictly necessary */
6142
6091
}
6143
6092
else
6144
6093
{
@@ -6211,16 +6160,13 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
6211
6160
/*
6212
6161
* It's an update; should we keep it? If the transaction is known
6213
6162
* aborted or crashed then it's okay to ignore it, otherwise not.
6163
+ * Note that an updater older than cutoff_xid cannot possibly be
6164
+ * committed, because HeapTupleSatisfiesVacuum would have returned
6165
+ * HEAPTUPLE_DEAD and we would not be trying to freeze the tuple.
6214
6166
*
6215
6167
* As with all tuple visibility routines, it's critical to test
6216
6168
* TransactionIdIsInProgress before TransactionIdDidCommit,
6217
6169
* because of race conditions explained in detail in tqual.c.
6218
- *
6219
- * We normally don't see committed updating transactions earlier
6220
- * than the cutoff xid, because they are removed by page pruning
6221
- * before we try to freeze the page; but it can happen if the
6222
- * updating transaction commits after the page is pruned but
6223
- * before HeapTupleSatisfiesVacuum.
6224
6170
*/
6225
6171
if (TransactionIdIsCurrentTransactionId (xid ) ||
6226
6172
TransactionIdIsInProgress (xid ))
@@ -6245,6 +6191,13 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
6245
6191
* we can ignore it.
6246
6192
*/
6247
6193
6194
+ /*
6195
+ * Since the tuple wasn't marked HEAPTUPLE_DEAD by vacuum, the
6196
+ * update Xid cannot possibly be older than the xid cutoff.
6197
+ */
6198
+ Assert (!TransactionIdIsValid (update_xid ) ||
6199
+ !TransactionIdPrecedes (update_xid , cutoff_xid ));
6200
+
6248
6201
/*
6249
6202
* If we determined that it's an Xid corresponding to an update
6250
6203
* that must be retained, additionally add it to the list of
@@ -6321,10 +6274,7 @@ FreezeMultiXactId(MultiXactId multi, uint16 t_infomask,
6321
6274
*
6322
6275
* It is assumed that the caller has checked the tuple with
6323
6276
* HeapTupleSatisfiesVacuum() and determined that it is not HEAPTUPLE_DEAD
6324
- * (else we should be removing the tuple, not freezing it). However, note
6325
- * that we don't remove HOT tuples even if they are dead, and it'd be incorrect
6326
- * to freeze them (because that would make them visible), so we mark them as
6327
- * update-committed, and needing further freezing later on.
6277
+ * (else we should be removing the tuple, not freezing it).
6328
6278
*
6329
6279
* NB: cutoff_xid *must* be <= the current global xmin, to ensure that any
6330
6280
* XID older than it could neither be running nor seen as running by any
@@ -6429,18 +6379,7 @@ heap_prepare_freeze_tuple(HeapTupleHeader tuple, TransactionId cutoff_xid,
6429
6379
else if (TransactionIdIsNormal (xid ) &&
6430
6380
TransactionIdPrecedes (xid , cutoff_xid ))
6431
6381
{
6432
- /*
6433
- * Must freeze regular XIDs older than the cutoff. We must not freeze
6434
- * a HOT-updated tuple, though; doing so would bring it back to life.
6435
- */
6436
- if (HeapTupleHeaderIsHotUpdated (tuple ))
6437
- {
6438
- frz -> t_infomask |= HEAP_XMAX_COMMITTED ;
6439
- changed = true;
6440
- /* must not freeze */
6441
- }
6442
- else
6443
- freeze_xmax = true;
6382
+ freeze_xmax = true;
6444
6383
}
6445
6384
6446
6385
if (freeze_xmax )
0 commit comments