diff options
author | Kyle Suarez <ksuarz@gmail.com> | 2016-04-29 15:47:47 -0400 |
---|---|---|
committer | Kyle Suarez <kyle.suarez@mongodb.com> | 2016-04-29 15:47:47 -0400 |
commit | dc729bf1e79318b17bcb02550ce7a0a51b814d72 (patch) | |
tree | 837b39cb1de8b0d1b3a983e84910b8099b7b544f /src | |
parent | 49365c2a1eb89cf6245e77bda1e10b1651d5d888 (diff) | |
download | mongo-dc729bf1e79318b17bcb02550ce7a0a51b814d72.tar.gz |
SERVER-23807 index build must X-lock collection
Index builds must lock the collection with an X lock, rather than an IX lock, to
prevent a race with concurrent updates.
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/commands/create_indexes.cpp | 11 | ||||
-rw-r--r-- | src/mongo/db/index_builder.cpp | 4 |
2 files changed, 13 insertions, 2 deletions
diff --git a/src/mongo/db/commands/create_indexes.cpp b/src/mongo/db/commands/create_indexes.cpp index 238fdc7c4cb..e906eb9c2ae 100644 --- a/src/mongo/db/commands/create_indexes.cpp +++ b/src/mongo/db/commands/create_indexes.cpp @@ -233,7 +233,16 @@ public: } try { - Lock::CollectionLock colLock(txn->lockState(), ns.ns(), MODE_IX); + // We need an X lock and not an IX lock due to a race with concurrent updates. Consider + // the following scenario: + // + // 1. A document is about to be indexed by a background index builder. + // 2. An update concurrently reads the same document. + // 3. The update unindexes the old value of the document. However, this is a no-op + // because the document wasn't previously indexed, so no write conflict is thrown. + // 4. Both the update and the index builder insert their respective index keys into the + // index, resulting in more keys in the index than expected. + Lock::CollectionLock colLock(txn->lockState(), ns.ns(), MODE_X); uassertStatusOK(indexer.insertAllDocumentsInCollection()); } catch (const DBException& e) { invariant(e.getCode() != ErrorCodes::WriteConflict); diff --git a/src/mongo/db/index_builder.cpp b/src/mongo/db/index_builder.cpp index ba2cbd6d6ef..0ed860c5dea 100644 --- a/src/mongo/db/index_builder.cpp +++ b/src/mongo/db/index_builder.cpp @@ -175,7 +175,9 @@ Status IndexBuilder::_build(OperationContext* txn, dbLock->relockWithMode(MODE_IX); } - Lock::CollectionLock colLock(txn->lockState(), ns.ns(), MODE_IX); + // We need an X lock and not an IX lock for background index building. See the + // createIndexes command for a detailed example. + Lock::CollectionLock colLock(txn->lockState(), ns.ns(), MODE_X); status = indexer.insertAllDocumentsInCollection(); } |