Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit e4828e9

Browse files
committed
Compare Xmin to previous Xmax when locking an update chain
Not doing so causes us to traverse an update chain that has been broken by concurrent page pruning. All other code that traverses update chains uses this check as one of the cases in which to stop iterating, so replicate it here too. Failure to do so leads to erroneous CLOG, subtrans or multixact lookups. Per discussion following the bug report by J Smith in CADFUPgc5bmtv-yg9znxV-vcfkb+JPRqs7m2OesQXaM_4Z1JpdQ@mail.gmail.com as diagnosed by Andres Freund.
1 parent c235a6a commit e4828e9

File tree

1 file changed

+14
-0
lines changed

1 file changed

+14
-0
lines changed

src/backend/access/heap/heapam.c

+14
Original file line numberDiff line numberDiff line change
@@ -4814,6 +4814,7 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
48144814
old_infomask;
48154815
TransactionId xmax,
48164816
new_xmax;
4817+
TransactionId priorXmax = InvalidTransactionId;
48174818

48184819
ItemPointerCopy(tid, &tupid);
48194820

@@ -4839,6 +4840,18 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
48394840
CHECK_FOR_INTERRUPTS();
48404841
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
48414842

4843+
/*
4844+
* Check the tuple XMIN against prior XMAX, if any. If we reached
4845+
* the end of the chain, we're done, so return success.
4846+
*/
4847+
if (TransactionIdIsValid(priorXmax) &&
4848+
!TransactionIdEquals(HeapTupleHeaderGetXmin(mytup.t_data),
4849+
priorXmax))
4850+
{
4851+
UnlockReleaseBuffer(buf);
4852+
return HeapTupleMayBeUpdated;
4853+
}
4854+
48424855
old_infomask = mytup.t_data->t_infomask;
48434856
xmax = HeapTupleHeaderGetRawXmax(mytup.t_data);
48444857

@@ -4939,6 +4952,7 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
49394952
}
49404953

49414954
/* tail recursion */
4955+
priorXmax = HeapTupleHeaderGetUpdateXid(mytup.t_data);
49424956
ItemPointerCopy(&(mytup.t_data->t_ctid), &tupid);
49434957
UnlockReleaseBuffer(buf);
49444958
}

0 commit comments

Comments
 (0)