diff options
author | Kyle Suarez <ksuarz@gmail.com> | 2016-04-20 16:18:11 -0400 |
---|---|---|
committer | Kyle Suarez <ksuarz@gmail.com> | 2016-04-21 15:12:26 -0400 |
commit | be81cc9e83d09d4dc206c59656fc7e51c3e4fc12 (patch) | |
tree | 398c5fc03a4088289e295936cbf93bf9dc6864d7 | |
parent | 7ed897882703723cc053faac6c3f634184caaa9f (diff) | |
download | mongo-be81cc9e83d09d4dc206c59656fc7e51c3e4fc12.tar.gz |
SERVER-22970 fix update race with background index build
There are two distinct fixes that must be done together:
- SERVER-23807: update should throw write conflict on unindex
- SERVER-18844: background index builds should reacquire the snapshot to
properly detect write conflicts with concurrent updates
-rw-r--r-- | src/mongo/db/catalog/index_create.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp | 20 |
2 files changed, 23 insertions, 1 deletions
diff --git a/src/mongo/db/catalog/index_create.cpp b/src/mongo/db/catalog/index_create.cpp index 1b2b3068530..0814277262f 100644 --- a/src/mongo/db/catalog/index_create.cpp +++ b/src/mongo/db/catalog/index_create.cpp @@ -259,6 +259,8 @@ Status MultiIndexBlock::insertAllDocumentsInCollection(std::set<RecordId>* dupsO WriteUnitOfWork wunit(_txn); Status ret = insert(objToIndex.value(), loc); + if (_buildInBackground) + exec->saveState(); if (ret.isOK()) { wunit.commit(); } else if (dupsOut && ret.code() == ErrorCodes::DuplicateKey) { @@ -269,6 +271,8 @@ Status MultiIndexBlock::insertAllDocumentsInCollection(std::set<RecordId>* dupsO // Fail the index build hard. return ret; } + if (_buildInBackground) + exec->restoreState(); // Handles any WCEs internally. // Go to the next document progress->hit(); diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp index 1708a02a44f..6d72225c597 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp @@ -1079,8 +1079,17 @@ void WiredTigerIndexUnique::_unindex(WT_CURSOR* c, // dups are allowed, so we have to deal with a vector of RecordIds. int ret = WT_OP_CHECK(c->search(c)); - if (ret == WT_NOTFOUND) + if (ret == WT_NOTFOUND) { + // WT_NOTFOUND is only expected during a background index build. Insert a dummy value and + // delete it again to trigger a write conflict in case this is being concurrently indexed by + // the background indexer. + c->set_key(c, keyItem.Get()); + c->set_value(c, emptyItem.Get()); + invariantWTOK(WT_OP_CHECK(c->insert(c))); + c->set_key(c, keyItem.Get()); + invariantWTOK(WT_OP_CHECK(c->remove(c))); return; + } invariantWTOK(ret); WT_ITEM old; @@ -1188,6 +1197,15 @@ void WiredTigerIndexStandard::_unindex(WT_CURSOR* c, int ret = WT_OP_CHECK(c->remove(c)); if (ret != WT_NOTFOUND) { invariantWTOK(ret); + } else { + // WT_NOTFOUND is only expected during a background index build. Insert a dummy value and + // delete it again to trigger a write conflict in case this is being concurrently indexed by + // the background indexer. + c->set_key(c, item.Get()); + c->set_value(c, emptyItem.Get()); + invariantWTOK(WT_OP_CHECK(c->insert(c))); + c->set_key(c, item.Get()); + invariantWTOK(WT_OP_CHECK(c->remove(c))); } } |