summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Cahill <michael.cahill@mongodb.com>2017-11-27 08:53:34 +1100
committerAlex Gorrod <alexander.gorrod@mongodb.com>2017-11-27 08:53:34 +1100
commit00374e0c7f1a356a30355f59d4bbb9e60bbd94d3 (patch)
tree36b7b9c13c1be30cef45dfcec1829f89e180b653
parentbc0337ed0085ea2d7b00f73deb2f726b4ffbee1b (diff)
downloadmongo-00374e0c7f1a356a30355f59d4bbb9e60bbd94d3.tar.gz
WT-3765 Prevent eviction of pages being truncated. (#3809)
When an application performs a truncate operation, WiredTiger marks pages deleted. If such a page is subsequently read with a view earlier than the truncate, the page is reinstantiated and all records deleted (as if truncate had taken the slow path). Such a page cannot be evicted: if the truncate is rolled back, it expects to find the page and any tombstones so it can roll them all back. If the page is evicted or split, the rollback will fail. This change takes two approaches: don't allow checkpoints to queue pages for urgent eviction, since checkpoints use special rules to determine whether eviction is permitted. In addition, check for uncommitted truncate operations before allowing any page to be evicted.
-rw-r--r--src/include/btree.i22
1 files changed, 18 insertions, 4 deletions
diff --git a/src/include/btree.i b/src/include/btree.i
index 19b300908b1..ae0c2b4908c 100644
--- a/src/include/btree.i
+++ b/src/include/btree.i
@@ -1336,6 +1336,14 @@ __wt_page_can_evict(WT_SESSION_IMPL *session, WT_REF *ref, bool *inmem_splitp)
return (false);
/*
+ * If the page was restored after a truncate, it can't be evicted until
+ * the truncate completes.
+ */
+ if (ref->page_del != NULL && !__wt_txn_visible_all(session,
+ ref->page_del->txnid, WT_TIMESTAMP_NULL(&ref->page_del->timestamp)))
+ return (false);
+
+ /*
* Check for in-memory splits before other eviction tests. If the page
* should split in-memory, return success immediately and skip more
* detailed eviction tests. We don't need further tests since the page
@@ -1423,15 +1431,21 @@ __wt_page_release(WT_SESSION_IMPL *session, WT_REF *ref, uint32_t flags)
*
* Fast checks if eviction is disabled for this handle, operation or
* tree, then perform a general check if eviction will be possible.
+ *
+ * Checkpoint should not queue pages for urgent eviction if it cannot
+ * evict them immediately: there is a special exemption that allows
+ * checkpoint to evict dirty pages in a tree that is being
+ * checkpointed, and no other thread can help with that.
*/
page = ref->page;
if (WT_READGEN_EVICT_SOON(page->read_gen) &&
btree->evict_disabled == 0 &&
__wt_page_can_evict(session, ref, &inmem_split)) {
- if ((LF_ISSET(WT_READ_NO_SPLIT) || (!inmem_split &&
- F_ISSET(session, WT_SESSION_NO_RECONCILE))))
- __wt_page_evict_urgent(session, ref);
- else {
+ if (LF_ISSET(WT_READ_NO_SPLIT) || (!inmem_split &&
+ F_ISSET(session, WT_SESSION_NO_RECONCILE))) {
+ if (!WT_SESSION_IS_CHECKPOINT(session))
+ __wt_page_evict_urgent(session, ref);
+ } else {
WT_RET_BUSY_OK(__wt_page_release_evict(session, ref));
return (0);
}