Thanks to visit codestin.com
Credit goes to github.com

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

Lines changed: 19 additions & 11 deletions
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)