summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Gorrod <alexander.gorrod@mongodb.com>2016-07-14 13:00:20 +1000
committerMichael Cahill <michael.cahill@mongodb.com>2016-07-14 13:00:20 +1000
commit0136888b3b677d67ff929c6f5b1f8d6aa6793b13 (patch)
treefa0d3b7c519c5bfb4b6dcaa75e0dadd737eeeb0f
parentc74568b31a5fa834349a91ec4295d9cc1e49c9b7 (diff)
downloadmongo-0136888b3b677d67ff929c6f5b1f8d6aa6793b13.tar.gz
WT-2725 Enforce visibility constraints before evicting a page. (#2875)
Otherwise there is a race between when we add a page to the queue and when the page is pulled off the queue - where the updates on the page may have changed, thus violating transactional constraints.
-rw-r--r--src/btree/bt_split.c5
-rw-r--r--src/evict/evict_lru.c19
-rw-r--r--src/include/btree.i18
-rw-r--r--src/meta/meta_track.c2
4 files changed, 20 insertions, 24 deletions
diff --git a/src/btree/bt_split.c b/src/btree/bt_split.c
index 39c10133542..28fcb60e95d 100644
--- a/src/btree/bt_split.c
+++ b/src/btree/bt_split.c
@@ -511,7 +511,8 @@ __split_deepen(WT_SESSION_IMPL *session, WT_PAGE *parent)
* array, a thread might see a freed WT_REF. Set the eviction
* transaction requirement for the newly created internal pages.
*/
- child->modify->mod_split_txn = __wt_txn_id_alloc(session, false);
+ child->modify->mod_split_txn =
+ __wt_txn_id_alloc(session, false);
/*
* The newly allocated child's page index references the same
@@ -865,7 +866,7 @@ __split_parent_lock(
}
/*
* If a checkpoint is running and we fail to lock the parent
- * page, give up immmediately to avoid deadlock.
+ * page, give up immediately to avoid deadlock.
*/
if (S2BT(session)->checkpointing)
return (EBUSY);
diff --git a/src/evict/evict_lru.c b/src/evict/evict_lru.c
index dc64a55091d..42966d636f6 100644
--- a/src/evict/evict_lru.c
+++ b/src/evict/evict_lru.c
@@ -1277,25 +1277,6 @@ fast: /* If the page can't be evicted, give up. */
!__wt_txn_visible_all(session, mod->rec_max_txn))
continue;
- /*
- * If the oldest transaction hasn't changed since the last time
- * this page was written, it's unlikely that we can make
- * progress. Similarly, if the most recent update on the page
- * is not yet globally visible, eviction will fail. These
- * heuristics attempt to avoid repeated attempts to evict the
- * same page.
- *
- * That said, if eviction is stuck, or we are helping with
- * forced eviction, try anyway: maybe a transaction that was
- * running last time we wrote the page has since rolled back,
- * or we can help get the checkpoint completed sooner.
- */
- if (modified && !LF_ISSET(
- WT_EVICT_PASS_AGGRESSIVE | WT_EVICT_PASS_WOULD_BLOCK) &&
- (mod->disk_snap_min == S2C(session)->txn_global.oldest_id ||
- !__wt_txn_visible_all(session, mod->update_txn)))
- continue;
-
WT_ASSERT(session, evict->ref == NULL);
__evict_init_candidate(session, evict, ref);
++evict;
diff --git a/src/include/btree.i b/src/include/btree.i
index 6dff3156d09..8086df92087 100644
--- a/src/include/btree.i
+++ b/src/include/btree.i
@@ -1073,6 +1073,7 @@ __wt_page_can_evict(WT_SESSION_IMPL *session,
WT_BTREE *btree;
WT_PAGE_MODIFY *mod;
WT_TXN_GLOBAL *txn_global;
+ bool modified;
if (inmem_splitp != NULL)
*inmem_splitp = false;
@@ -1109,6 +1110,8 @@ __wt_page_can_evict(WT_SESSION_IMPL *session,
!__wt_txn_visible_all(session, mod->mod_split_txn))
return (false);
+ modified = __wt_page_is_modified(page);
+
/*
* If the file is being checkpointed, we can't evict dirty pages:
* if we write a page and free the previous version of the page, that
@@ -1116,8 +1119,7 @@ __wt_page_can_evict(WT_SESSION_IMPL *session,
* been written in the checkpoint, leaving the checkpoint inconsistent.
*/
if (btree->checkpointing &&
- (__wt_page_is_modified(page) ||
- mod->rec_result == WT_PM_REC_MULTIBLOCK)) {
+ (modified || mod->rec_result == WT_PM_REC_MULTIBLOCK)) {
WT_STAT_FAST_CONN_INCR(session, cache_eviction_checkpoint);
WT_STAT_FAST_DATA_INCR(session, cache_eviction_checkpoint);
return (false);
@@ -1133,6 +1135,18 @@ __wt_page_can_evict(WT_SESSION_IMPL *session,
return (false);
}
+ /*
+ * If the oldest transaction hasn't changed since the last time this
+ * page was written, it's unlikely that we can make progress.
+ * Similarly, if the most recent update on the page is not yet globally
+ * visible, eviction must fail. These checks also aim to avoid
+ * repeated attempts to evict the same page.
+ */
+ if (modified &&
+ (mod->disk_snap_min == __wt_txn_oldest_id(session) ||
+ !__wt_txn_visible_all(session, mod->update_txn)))
+ return (false);
+
return (true);
}
diff --git a/src/meta/meta_track.c b/src/meta/meta_track.c
index b8d7aa930ea..6c8296a9bdd 100644
--- a/src/meta/meta_track.c
+++ b/src/meta/meta_track.c
@@ -487,7 +487,7 @@ __wt_meta_track_handle_lock(WT_SESSION_IMPL *session, bool created)
/*
* __wt_meta_track_init --
- * Intialize metadata tracking.
+ * Initialize metadata tracking.
*/
int
__wt_meta_track_init(WT_SESSION_IMPL *session)