summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Gorrod <alexg@wiredtiger.com>2015-07-24 15:55:29 +1000
committerMichael Cahill <michael.cahill@mongodb.com>2015-08-06 15:59:48 +1000
commitcd8c1e8312224017cf2ee2cc1bb0649a5b574b2d (patch)
tree74621fe7cb0207a14bb1ef31d279c2508c58241a
parent7cb51cd688c2375a504f99d5c57674e7fdfbcee0 (diff)
downloadmongo-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)
-rw-r--r--src/txn/txn.c30
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);