diff options
author | Michael Cahill <michael.cahill@wiredtiger.com> | 2014-08-27 22:24:16 +1000 |
---|---|---|
committer | Michael Cahill <michael.cahill@wiredtiger.com> | 2014-08-27 22:24:16 +1000 |
commit | a31ef5ee5aff1f65065335f7a60772889f1484bd (patch) | |
tree | 003b4858ca2de7aba91aff3e3d49e4b0c830b881 /src/txn | |
parent | 2b001bf983984be7f2ca78654a2f32f184afba2e (diff) | |
download | mongo-a31ef5ee5aff1f65065335f7a60772889f1484bd.tar.gz |
Don't reset cursors during transaction begin or commit (only on rollback).
Diffstat (limited to 'src/txn')
-rw-r--r-- | src/txn/txn.c | 62 |
1 files changed, 33 insertions, 29 deletions
diff --git a/src/txn/txn.c b/src/txn/txn.c index 7db3205ba97..bf07393f608 100644 --- a/src/txn/txn.c +++ b/src/txn/txn.c @@ -83,7 +83,7 @@ __wt_txn_update_oldest(WT_SESSION_IMPL *session) * state wasn't refreshed after the last transaction committed. Push * past the last committed transaction. */ - __wt_txn_refresh(session, WT_TXN_NONE, 0); + __wt_txn_refresh(session, 0, 0); } /* @@ -91,7 +91,8 @@ __wt_txn_update_oldest(WT_SESSION_IMPL *session) * Allocate a transaction ID and/or a snapshot. */ void -__wt_txn_refresh(WT_SESSION_IMPL *session, uint64_t max_id, int get_snapshot) +__wt_txn_refresh( + WT_SESSION_IMPL *session, int get_snapshot, int pin_reads) { WT_CONNECTION_IMPL *conn; WT_TXN *txn; @@ -135,27 +136,23 @@ __wt_txn_refresh(WT_SESSION_IMPL *session, uint64_t max_id, int get_snapshot) /* 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; - - /* If the maximum ID is constrained, so is the oldest. */ - oldest_id = (max_id != WT_TXN_NONE) ? max_id : snap_min; + current_id = oldest_id = snap_min = txn_global->current; /* Walk the array of concurrent transactions. */ WT_ORDERED_READ(session_cnt, conn->session_cnt); for (i = n = 0, s = txn_global->states; i < session_cnt; i++, s++) { /* - * Ignore the ID if we are committing (indicated by max_id - * being set): it is about to be released. + * Build our snapshot of any concurrent transaction IDs. + * + * Ignore our own ID: we always read our own updates. * * Also ignore the ID if it is older than the oldest ID we saw. * This can happen if we race with a thread that is allocating * an ID -- the ID will not be used because the thread will * keep spinning until it gets a valid one. - * - * Lastly, ignore the checkpoint transaction ID: checkpoints - * never do application-visible updates. */ - if ((id = s->id) != WT_TXN_NONE && id + 1 != max_id && + if (s != txn_state && + (id = s->id) != WT_TXN_NONE && TXNID_LE(prev_oldest_id, id)) { if (get_snapshot) txn->snapshot[n++] = id; @@ -167,7 +164,7 @@ __wt_txn_refresh(WT_SESSION_IMPL *session, uint64_t max_id, int get_snapshot) * Ignore the session's own snap_min if we are in the process * of updating it. */ - if (get_snapshot && s == txn_state) + if (get_snapshot && !pin_reads && s == txn_state) continue; /* @@ -185,8 +182,17 @@ __wt_txn_refresh(WT_SESSION_IMPL *session, uint64_t max_id, int get_snapshot) if (TXNID_LT(snap_min, oldest_id)) oldest_id = snap_min; + if (txn->id != WT_TXN_NONE && TXNID_LT(txn->id, oldest_id)) + oldest_id = txn->id; - if (get_snapshot) { + /* + * If we got a new snapshot, update the published snap_min for this + * session. Skip this if we are updating a snapshot because there are + * positioned cursors during commit: the cursors may be pointing to + * data older than the snapshot we've calculated. + */ + if (get_snapshot && !pin_reads && + (session->ncursors == 0 || txn_state->snap_min == WT_TXN_NONE)) { WT_ASSERT(session, TXNID_LE(prev_oldest_id, snap_min)); WT_ASSERT(session, prev_oldest_id == txn_global->oldest_id); txn_state->snap_min = snap_min; @@ -205,9 +211,8 @@ __wt_txn_refresh(WT_SESSION_IMPL *session, uint64_t max_id, int get_snapshot) * much newer value. Once we get exclusive access, do another pass to * make sure nobody else is using an earlier ID. */ - if (max_id == WT_TXN_NONE && - (TXNID_LT(prev_oldest_id, oldest_id) && - (!get_snapshot || oldest_id - prev_oldest_id > 100)) && + if (TXNID_LT(prev_oldest_id, oldest_id) && + (!get_snapshot || oldest_id - prev_oldest_id > 100) && WT_ATOMIC_CAS(txn_global->scan_count, 1, -1)) { WT_ORDERED_READ(session_cnt, conn->session_cnt); for (i = 0, s = txn_global->states; i < session_cnt; i++, s++) { @@ -264,7 +269,7 @@ __wt_txn_begin(WT_SESSION_IMPL *session, const char *cfg[]) F_SET(txn, TXN_RUNNING); if (txn->isolation == TXN_ISO_SNAPSHOT) - __wt_txn_refresh(session, WT_TXN_NONE, 1); + __wt_txn_refresh(session, 1, session->ncursors > 0); return (0); } @@ -302,10 +307,8 @@ __wt_txn_release(WT_SESSION_IMPL *session) __wt_split_stash_discard(session); /* - * Reset the transaction state to not running. - * - * Auto-commit transactions (identified by having active cursors) - * handle this at a higher level. + * Reset the transaction state to not running. Release the snapshot + * if no cursors are active. */ if (session->ncursors == 0) __wt_txn_release_snapshot(session); @@ -359,17 +362,18 @@ __wt_txn_commit(WT_SESSION_IMPL *session, const char *cfg[]) txn->mod_count = 0; /* - * Auto-commit transactions need a new transaction snapshot so that the - * committed changes are visible to subsequent reads. However, cursor - * keys and values will point to the data that was just modified, so - * the snapshot cannot be so new that updates could be freed underneath - * the cursor. Get the new snapshot before releasing the ID for the - * commit. + * Positioned cursors need a new transaction snapshot so that the + * committed changes are visible to reads after this transaction clears + * its ID. However, cursor keys and values will point to the data that + * was just modified, so the snapshot cannot be so new that updates + * could be freed underneath the cursor. Get the new snapshot before + * releasing the ID for the commit. */ if (session->ncursors > 0 && F_ISSET(txn, TXN_HAS_ID) && txn->isolation != TXN_ISO_READ_UNCOMMITTED) - __wt_txn_refresh(session, txn->id + 1, 1); + __wt_txn_refresh(session, 1, 1); + __wt_txn_release(session); return (0); } |