From be81cc9e83d09d4dc206c59656fc7e51c3e4fc12 Mon Sep 17 00:00:00 2001 From: Kyle Suarez Date: Wed, 20 Apr 2016 16:18:11 -0400 Subject: 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 --- src/mongo/db/catalog/index_create.cpp | 4 ++++ src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp | 20 +++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) 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* 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* 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))); } } -- cgit v1.2.1