diff options
-rw-r--r-- | src/evict/evict_lru.c | 54 | ||||
-rw-r--r-- | src/include/btmem.h | 3 | ||||
-rw-r--r-- | src/include/btree.i | 19 | ||||
-rw-r--r-- | src/reconcile/rec_write.c | 6 |
4 files changed, 62 insertions, 20 deletions
diff --git a/src/evict/evict_lru.c b/src/evict/evict_lru.c index dd2f58c43fa..0207798bdb9 100644 --- a/src/evict/evict_lru.c +++ b/src/evict/evict_lru.c @@ -1196,26 +1196,44 @@ fast: /* If the page can't be evicted, give up. */ continue; /* - * If the oldest transaction hasn't changed since the last time - * this page was written, it's unlikely we can make progress (an - * heuristic to avoid repeated attempts to evict the same page). - * Similarly, if the most recent update on the page is not yet - * committed, eviction will fail. + * Additional tests if eviction is likely to succeed. * - * 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. - * - * Note: take care with ordering: if we detected that the page - * is modified above, we expect mod != NULL. + * 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 the + * checkpoint complete sooner. Additionally, being stuck will + * configure lookaside file writes in reconciliation, allowing + * us to evict pages we can't usually evict. */ - mod = page->modify; - if (modified && !FLD_ISSET(cache->state, - WT_EVICT_PASS_AGGRESSIVE | WT_EVICT_PASS_WOULD_BLOCK) && - (!__wt_txn_committed(session, mod->update_txn) || - mod->disk_snap_min == conn->txn_global.oldest_id)) - continue; + if (!FLD_ISSET(cache->state, + WT_EVICT_PASS_AGGRESSIVE | WT_EVICT_PASS_WOULD_BLOCK)) { + /* + * Note: take care with ordering: if we detected that + * the page is modified above, we expect mod != NULL. + */ + mod = page->modify; + + /* + * If the page is clean but has modifications that + * appear too new to evict, skip it. + */ + if (!modified && mod != NULL && + !__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 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. + */ + if (modified && + (mod->disk_snap_min == conn->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); diff --git a/src/include/btmem.h b/src/include/btmem.h index 5f713877373..a813dce48a0 100644 --- a/src/include/btmem.h +++ b/src/include/btmem.h @@ -209,6 +209,9 @@ struct __wt_page_modify { /* Avoid checking for obsolete updates during checkpoints. */ uint64_t obsolete_check_txn; + /* The largest transaction ID seen on the page by reconciliation. */ + uint64_t rec_max_txn; + /* The largest update transaction ID (approximate). */ uint64_t update_txn; diff --git a/src/include/btree.i b/src/include/btree.i index 58a66738aa2..40858175ca4 100644 --- a/src/include/btree.i +++ b/src/include/btree.i @@ -975,6 +975,7 @@ __wt_page_can_evict(WT_SESSION_IMPL *session, WT_BTREE *btree; WT_PAGE_MODIFY *mod; WT_TXN_GLOBAL *txn_global; + uint64_t txnid; if (inmem_splitp != NULL) *inmem_splitp = 0; @@ -1044,9 +1045,23 @@ __wt_page_can_evict(WT_SESSION_IMPL *session, * for existing hazard pointers, the checkpoint thread reconciling an * internal page acquires hazard pointers on child pages it reads, and * is blocked by the exclusive lock. - * - * KEITH: this comment should move to somewhere else. */ + if (page->read_gen != WT_READGEN_OLDEST) { + /* + * If eviction is stuck, we'll use the lookaside file and so + * only care if all changes on the page are committed. + */ + if (__wt_eviction_aggressive(session)) { + if (__wt_page_is_modified(page) && + !__wt_txn_committed(session, mod->update_txn)) + return (0); + } else { + if (!__wt_txn_visible_all(session, + __wt_page_is_modified(page) ? + mod->update_txn : mod->rec_max_txn)) + return (0); + } + } /* * If the page was recently split in-memory, don't force it out: we diff --git a/src/reconcile/rec_write.c b/src/reconcile/rec_write.c index 2ccbe1a1ab1..81cd2e673e9 100644 --- a/src/reconcile/rec_write.c +++ b/src/reconcile/rec_write.c @@ -5506,6 +5506,12 @@ err: __wt_scr_free(session, &tkey); return (EBUSY); } else { /* + * Track the page's maximum transaction ID (used to decide if + * we're likely to be able to evict this page in the future). + */ + mod->rec_max_txn = r->max_txn; + + /* * Track the tree's maximum transaction ID (used to decide if * it's safe to discard the tree). Reconciliation for eviction * is multi-threaded, only update the tree's maximum transaction |