diff options
author | Michael Cahill <michael.cahill@wiredtiger.com> | 2013-01-08 00:35:34 +1100 |
---|---|---|
committer | Michael Cahill <michael.cahill@wiredtiger.com> | 2013-01-08 00:35:34 +1100 |
commit | 1a52f63a8d06060c98ef299e958850c8ec528f77 (patch) | |
tree | 9a8bf09fd2ed3b32afdc6eeebaa840718af1fe68 | |
parent | bb550b2b748c77e3abee02d8b2e5465df89521e8 (diff) | |
download | mongo-1a52f63a8d06060c98ef299e958850c8ec528f77.tar.gz |
Skip eviction of dirty pages when a checkpoint is in progress. There are cases where transactinal reads are not sufficient to guarantee that no page referenced from the checkpoint will be overwritten.
closes #425
-rw-r--r-- | src/btree/rec_evict.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/src/btree/rec_evict.c b/src/btree/rec_evict.c index e61f8c890cb..b739e644099 100644 --- a/src/btree/rec_evict.c +++ b/src/btree/rec_evict.c @@ -279,8 +279,17 @@ __rec_review(WT_SESSION_IMPL *session, } /* - * If the file is being checkpointed, the checkpoint's reconciliation of - * an internal page might race with us as we evict a child in the page's + * If the file is being checkpointed, we cannot evict dirty pages, + * because that may free a page that appears on an internal page in the + * checkpoint. Don't rely on new updates being skipped by the + * transaction used for transaction reads: (1) there are paths that + * dirty pages for artificial reasons; (2) internal pages aren't + * transactional; and (3) if an update was skipped during the + * checkpoint (leaving the page dirty), then rolled back, we could + * still successfully overwrite a page and corrupt the checkpoint. + * + * Further, even for clean pages, the checkpoint's reconciliation of an + * internal page might race with us as we evict a child in the page's * subtree. * * One half of that test is in the reconciliation code: the checkpoint @@ -311,6 +320,9 @@ __rec_review(WT_SESSION_IMPL *session, * we find a page which can't be merged into its parent, and failing if * we never find such a page. */ + if (btree->checkpointing && __wt_page_is_modified(page)) + return (EBUSY); + if (btree->checkpointing && top) for (t = page->parent;; t = t->parent) { if (t == NULL || t->ref == NULL) /* root */ |