summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKyle Suarez <ksuarz@gmail.com>2016-04-29 15:47:47 -0400
committerKyle Suarez <kyle.suarez@mongodb.com>2016-04-29 15:47:47 -0400
commitdc729bf1e79318b17bcb02550ce7a0a51b814d72 (patch)
tree837b39cb1de8b0d1b3a983e84910b8099b7b544f /src
parent49365c2a1eb89cf6245e77bda1e10b1651d5d888 (diff)
downloadmongo-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.cpp11
-rw-r--r--src/mongo/db/index_builder.cpp4
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();
}