v1-0002-Fix-the-bug-with-priorXmax.patch
text/x-patch
Filename: v1-0002-Fix-the-bug-with-priorXmax.patch
Type: text/x-patch
Part: 1
Message:
Re: Visibility bug in tuple lock
From 138b11e1a787f0d2b3fc913eec3c8d28527ee76c Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Thu, 11 Dec 2025 18:03:10 +0200
Subject: [PATCH v1 2/2] Fix the bug with priorXmax
---
src/backend/access/heap/heapam.c | 28 ++++++++++++++++++++++------
1 file changed, 22 insertions(+), 6 deletions(-)
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index a69df8bd431..5fb81af8d4f 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -86,6 +86,7 @@ static void compute_new_xmax_infomask(TransactionId xmax, uint16 old_infomask,
TransactionId *result_xmax, uint16 *result_infomask,
uint16 *result_infomask2);
static TM_Result heap_lock_updated_tuple(Relation rel, HeapTuple tuple,
+ TransactionId priorXmax,
const ItemPointerData *ctid, TransactionId xid,
LockTupleMode mode);
static void GetMultiXactIdHintBits(MultiXactId multi, uint16 *new_infomask,
@@ -4818,9 +4819,16 @@ l3:
*/
if (follow_updates && updated)
{
+ TransactionId updateXid;
TM_Result res;
- res = heap_lock_updated_tuple(relation, tuple, &t_ctid,
+ if (infomask & HEAP_XMAX_IS_MULTI)
+ updateXid = MultiXactIdGetUpdateXid(xwait, infomask);
+ else
+ updateXid = xwait;
+
+ res = heap_lock_updated_tuple(relation, tuple, updateXid,
+ &t_ctid,
GetCurrentTransactionId(),
mode);
if (res != TM_Ok)
@@ -5065,9 +5073,16 @@ l3:
/* if there are updates, follow the update chain */
if (follow_updates && !HEAP_XMAX_IS_LOCKED_ONLY(infomask))
{
+ TransactionId updateXid;
TM_Result res;
- res = heap_lock_updated_tuple(relation, tuple, &t_ctid,
+ if (infomask & HEAP_XMAX_IS_MULTI)
+ updateXid = MultiXactIdGetUpdateXid(xwait, infomask);
+ else
+ updateXid = xwait;
+
+ res = heap_lock_updated_tuple(relation, tuple, updateXid,
+ &t_ctid,
GetCurrentTransactionId(),
mode);
if (res != TM_Ok)
@@ -5721,7 +5736,8 @@ test_lockmode_for_conflict(MultiXactStatus status, TransactionId xid,
* version as well.
*/
static TM_Result
-heap_lock_updated_tuple_rec(Relation rel, const ItemPointerData *tid, TransactionId xid,
+heap_lock_updated_tuple_rec(Relation rel, TransactionId priorXmax,
+ const ItemPointerData *tid, TransactionId xid,
LockTupleMode mode)
{
TM_Result result;
@@ -5734,7 +5750,6 @@ heap_lock_updated_tuple_rec(Relation rel, const ItemPointerData *tid, Transactio
old_infomask2;
TransactionId xmax,
new_xmax;
- TransactionId priorXmax = InvalidTransactionId;
bool cleared_all_frozen = false;
bool pinned_desired_page;
Buffer vmbuffer = InvalidBuffer;
@@ -6066,7 +6081,8 @@ out_unlocked:
* levels, because that would lead to a serializability failure.
*/
static TM_Result
-heap_lock_updated_tuple(Relation rel, HeapTuple tuple, const ItemPointerData *ctid,
+heap_lock_updated_tuple(Relation rel, HeapTuple tuple, TransactionId priorXmax,
+ const ItemPointerData *ctid,
TransactionId xid, LockTupleMode mode)
{
INJECTION_POINT("heap_lock_updated_tuple", NULL);
@@ -6089,7 +6105,7 @@ heap_lock_updated_tuple(Relation rel, HeapTuple tuple, const ItemPointerData *ct
*/
MultiXactIdSetOldestMember();
- return heap_lock_updated_tuple_rec(rel, ctid, xid, mode);
+ return heap_lock_updated_tuple_rec(rel, priorXmax, ctid, xid, mode);
}
/* nothing to lock */
--
2.47.3