diff options
author | Alex Gorrod <alexg@wiredtiger.com> | 2015-07-24 15:55:29 +1000 |
---|---|---|
committer | Michael Cahill <michael.cahill@mongodb.com> | 2015-08-06 15:59:48 +1000 |
commit | cd8c1e8312224017cf2ee2cc1bb0649a5b574b2d (patch) | |
tree | 74621fe7cb0207a14bb1ef31d279c2508c58241a /src | |
parent | 7cb51cd688c2375a504f99d5c57674e7fdfbcee0 (diff) | |
download | mongo-cd8c1e8312224017cf2ee2cc1bb0649a5b574b2d.tar.gz |
WT-2021: Fix a race when getting a transaction ID.
There was a case where we thought the system was read-only. We could
assign a transaction ID that wasn't subsequently seen by an oldest
ID update.
(cherry picked from commit 32a59be7f48caf5bdda408282737ca04b667fae9)
Diffstat (limited to 'src')
-rw-r--r-- | src/txn/txn.c | 30 |
1 files changed, 14 insertions, 16 deletions
diff --git a/src/txn/txn.c b/src/txn/txn.c index 27cf8740132..a391ec8be88 100644 --- a/src/txn/txn.c +++ b/src/txn/txn.c @@ -87,20 +87,6 @@ __wt_txn_get_snapshot(WT_SESSION_IMPL *session) txn_global = &conn->txn_global; txn_state = WT_SESSION_TXN_STATE(session); - current_id = snap_min = txn_global->current; - prev_oldest_id = txn_global->oldest_id; - - /* For pure read-only workloads, avoid scanning. */ - if (prev_oldest_id == current_id) { - txn_state->snap_min = current_id; - __txn_sort_snapshot(session, 0, current_id); - - /* Check that the oldest ID has not moved in the meantime. */ - if (prev_oldest_id == txn_global->oldest_id && - txn_global->scan_count == 0) - return; - } - /* * We're going to scan. Increment the count of scanners to prevent the * oldest ID from moving forwards. Spin if the count is negative, @@ -112,9 +98,21 @@ __wt_txn_get_snapshot(WT_SESSION_IMPL *session) } while (count < 0 || !WT_ATOMIC_CAS4(txn_global->scan_count, count, count + 1)); - /* The oldest ID cannot change until the scan count goes to zero. */ - prev_oldest_id = txn_global->oldest_id; current_id = snap_min = txn_global->current; + prev_oldest_id = txn_global->oldest_id; + + /* For pure read-only workloads, avoid scanning. */ + if (prev_oldest_id == current_id) { + txn_state->snap_min = current_id; + __txn_sort_snapshot(session, 0, current_id); + + /* Check that the oldest ID has not moved in the meantime. */ + if (prev_oldest_id == txn_global->oldest_id) { + WT_ASSERT(session, txn_global->scan_count > 0); + (void)WT_ATOMIC_SUB4(txn_global->scan_count, 1); + return; + } + } /* Walk the array of concurrent transactions. */ WT_ORDERED_READ(session_cnt, conn->session_cnt); |