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

Commit 165d921

Browse files
committed
Fix wrong logic in TransactionIdInRecentPast()
The TransactionIdInRecentPast() should return false for all the transactions older than TransamVariables->oldestClogXid. However, the function contains a bug in comparison FullTransactionId to TransactionID allowing full transactions between nextXid - 2^32 and oldestClogXid - 2^31. This commit fixes TransactionIdInRecentPast() by turning the oldestClogXid into FullTransactionId first, then performing the comparison. Backpatch to all supported versions. Reported-by: Egor Chindyaskin Bug: 18212 Discussion: https://postgr.es/m/18212-547307f8adf57262%40postgresql.org Author: Karina Litskevich Reviewed-by: Kyotaro Horiguchi Backpatch-through: 12
1 parent 5869aef commit 165d921

File tree

1 file changed

+19
-11
lines changed

1 file changed

+19
-11
lines changed

src/backend/utils/adt/xid8funcs.c

+19-11
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,12 @@ StaticAssertDecl(MAX_BACKENDS * 2 <= PG_SNAPSHOT_MAX_NXIP,
9898
static bool
9999
TransactionIdInRecentPast(FullTransactionId fxid, TransactionId *extracted_xid)
100100
{
101-
uint32 xid_epoch = EpochFromFullTransactionId(fxid);
102101
TransactionId xid = XidFromFullTransactionId(fxid);
103102
uint32 now_epoch;
104103
TransactionId now_epoch_next_xid;
105104
FullTransactionId now_fullxid;
105+
TransactionId oldest_xid;
106+
FullTransactionId oldest_fxid;
106107

107108
now_fullxid = ReadNextFullTransactionId();
108109
now_epoch_next_xid = XidFromFullTransactionId(now_fullxid);
@@ -135,17 +136,24 @@ TransactionIdInRecentPast(FullTransactionId fxid, TransactionId *extracted_xid)
135136
Assert(LWLockHeldByMe(XactTruncationLock));
136137

137138
/*
138-
* If the transaction ID has wrapped around, it's definitely too old to
139-
* determine the commit status. Otherwise, we can compare it to
140-
* TransamVariables->oldestClogXid to determine whether the relevant CLOG
141-
* entry is guaranteed to still exist.
139+
* If fxid is not older than TransamVariables->oldestClogXid, the relevant
140+
* CLOG entry is guaranteed to still exist. Convert
141+
* TransamVariables->oldestClogXid into a FullTransactionId to compare it
142+
* with fxid. Determine the right epoch knowing that oldest_fxid
143+
* shouldn't be more than 2^31 older than now_fullxid.
142144
*/
143-
if (xid_epoch + 1 < now_epoch
144-
|| (xid_epoch + 1 == now_epoch && xid < now_epoch_next_xid)
145-
|| TransactionIdPrecedes(xid, TransamVariables->oldestClogXid))
146-
return false;
147-
148-
return true;
145+
oldest_xid = TransamVariables->oldestClogXid;
146+
Assert(TransactionIdPrecedesOrEquals(oldest_xid, now_epoch_next_xid));
147+
if (oldest_xid <= now_epoch_next_xid)
148+
{
149+
oldest_fxid = FullTransactionIdFromEpochAndXid(now_epoch, oldest_xid);
150+
}
151+
else
152+
{
153+
Assert(now_epoch > 0);
154+
oldest_fxid = FullTransactionIdFromEpochAndXid(now_epoch - 1, oldest_xid);
155+
}
156+
return !FullTransactionIdPrecedes(fxid, oldest_fxid);
149157
}
150158

151159
/*

0 commit comments

Comments
 (0)