summaryrefslogtreecommitdiff
path: root/src/mongo/db/commands/create_indexes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/commands/create_indexes.cpp')
-rw-r--r--src/mongo/db/commands/create_indexes.cpp11
1 files changed, 10 insertions, 1 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);