diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index f55e612590..39e5d2d26a 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -4814,6 +4814,7 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid, old_infomask; TransactionId xmax, new_xmax; + TransactionId priorXmax = InvalidTransactionId; ItemPointerCopy(tid, &tupid); @@ -4839,6 +4840,18 @@ l4: CHECK_FOR_INTERRUPTS(); LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE); + /* + * Check the tuple XMIN against prior XMAX, if any. If we reached + * the end of the chain, we're done, so return success. + */ + if (TransactionIdIsValid(priorXmax) && + !TransactionIdEquals(HeapTupleHeaderGetXmin(mytup.t_data), + priorXmax)) + { + UnlockReleaseBuffer(buf); + return HeapTupleMayBeUpdated; + } + old_infomask = mytup.t_data->t_infomask; xmax = HeapTupleHeaderGetRawXmax(mytup.t_data); @@ -4939,6 +4952,7 @@ l4: } /* tail recursion */ + priorXmax = HeapTupleHeaderGetUpdateXid(mytup.t_data); ItemPointerCopy(&(mytup.t_data->t_ctid), &tupid); UnlockReleaseBuffer(buf); }