summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Suarez <ksuarz@gmail.com>2016-04-20 16:18:11 -0400
committerKyle Suarez <ksuarz@gmail.com>2016-04-21 15:12:26 -0400
commitbe81cc9e83d09d4dc206c59656fc7e51c3e4fc12 (patch)
tree398c5fc03a4088289e295936cbf93bf9dc6864d7
parent7ed897882703723cc053faac6c3f634184caaa9f (diff)
downloadmongo-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.cpp4
-rw-r--r--src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp20
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)));
}
}