diff options
author | Alex Gorrod <alexander.gorrod@mongodb.com> | 2016-07-14 13:00:20 +1000 |
---|---|---|
committer | Michael Cahill <michael.cahill@mongodb.com> | 2016-07-14 13:00:20 +1000 |
commit | 0136888b3b677d67ff929c6f5b1f8d6aa6793b13 (patch) | |
tree | fa0d3b7c519c5bfb4b6dcaa75e0dadd737eeeb0f | |
parent | c74568b31a5fa834349a91ec4295d9cc1e49c9b7 (diff) | |
download | mongo-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.c | 5 | ||||
-rw-r--r-- | src/evict/evict_lru.c | 19 | ||||
-rw-r--r-- | src/include/btree.i | 18 | ||||
-rw-r--r-- | src/meta/meta_track.c | 2 |
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) |