-
Type:
Bug
-
Resolution: Fixed
-
Priority:
Minor - P4
-
Affects Version/s: None
-
Component/s: Logging
-
None
-
Environment:GCC 13, Ubuntu 24.04
-
Storage Engines - Transactions
-
264.291
-
None
-
1
During transaction table scanning, __txn_oldest_scan (txn.c line 407) calculates the global oldest transaction ID required (oldest_id) by finding the minimum of active running transaction IDs (last_running, tracked from s->id) and active read snapshot pinned IDs (s->pinned_id). While oldest_session is updated when scanning s->pinned_id < oldest_id inside the loop, the loop does not record the session associated with last_running. When last_running < oldest_id evaluates to true after the loop (line 477), oldest_id is updated to last_running, but oldest_session is not updated. If no session holds a pinned read snapshot, oldest_session remains NULL, causing __wt_txn_update_oldest (line 588) to silently evaluate oldest_session != NULL to false and suppress diagnostic verbose transaction logging (WT_VERB_TRANSACTION). Alternatively, if another session holds a higher pinned read snapshot, oldest_session points to the wrong session, falsely attributing the oldest transaction ID.
For ReProduce;
A catch2 unit test (test_txn_oldest_scan.cpp) reproduces the bug and verifies the fix. (I added before/after outputs on JIRA).
In a scenario where Session 1 has an active write transaction ID (s->id) without an active read snapshot (s->pinned_id == WT_TXN_NONE), __txn_oldest_scan returns oldest_session == nullptr without the fix, causing CHECK(oldest_session == session1) to fail.
With the fix, __txn_oldest_scan correctly identifies Session 1 and the test passes.
Proposed Fix
The fix tracks last_running_session alongside last_running during transaction array traversal in __txn_oldest_scan (txn.c), and assigns oldest_session = last_running_session; inside the if (last_running < oldest_id) block on line 478.