summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2020-11-19 13:07:23 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-11-19 22:20:14 +0000
commit77554e9e4fd18811d6df84d8934c888814d034ec (patch)
tree2003d4df1d93d9adc40f406ffac96788f91a7fa0
parent4739fb232284a655f0ae89c9a43490ed2219cb5e (diff)
downloadmongo-77554e9e4fd18811d6df84d8934c888814d034ec.tar.gz
SERVER-49249 initial sync skips single-phase index build if there is an index build already in progress
-rw-r--r--jstests/replsets/initial_sync_index_conflict.js10
-rw-r--r--src/mongo/db/repl/oplog.cpp25
2 files changed, 27 insertions, 8 deletions
diff --git a/jstests/replsets/initial_sync_index_conflict.js b/jstests/replsets/initial_sync_index_conflict.js
index c1af06307a1..b96c7f17176 100644
--- a/jstests/replsets/initial_sync_index_conflict.js
+++ b/jstests/replsets/initial_sync_index_conflict.js
@@ -67,19 +67,15 @@ try {
// Resume initial sync. The createIndexes oplog entry will be applied.
failPoint.off();
- assert.soon(function() {
- return rawMongoProgramOutput().search(
- /Invariant failure.*indexSpecs.size\(\) > 1.*test.coll.*a_1.*multi_index_block\.cpp/) >=
- 0;
- });
+ // Wait for initial sync to finish.
+ rst.awaitSecondaryNodes();
} finally {
+ IndexBuildTest.resumeIndexBuilds(secondary);
IndexBuildTest.resumeIndexBuilds(primary);
createIdx();
}
IndexBuildTest.assertIndexes(primaryColl, 2, ['_id_', 'a_1']);
-rst.stop(secondary, undefined, {allowedExitCode: MongoRunner.EXIT_ABORT});
-TestData.skipCheckDBHashes = true;
rst.stopSet();
})();
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp
index 1ea29defe74..d8c95789f04 100644
--- a/src/mongo/db/repl/oplog.cpp
+++ b/src/mongo/db/repl/oplog.cpp
@@ -194,6 +194,30 @@ void createIndexForApplyOps(OperationContext* opCtx,
opCtx->getWriteConcern());
}
+ // Check for conflict with two-phase index builds during initial sync. It is possible that
+ // this index may have been dropped and recreated after inserting documents into the collection.
+ auto indexBuildsCoordinator = IndexBuildsCoordinator::get(opCtx);
+ if (OplogApplication::Mode::kInitialSync == mode) {
+ auto normalSpecs =
+ indexBuildsCoordinator->normalizeIndexSpecs(opCtx, indexCollection, {indexSpec});
+ invariant(1U == normalSpecs.size(),
+ str::stream() << "Unexpected result from normalizeIndexSpecs - ns: " << indexNss
+ << "; uuid: " << indexCollection->uuid()
+ << "; original index spec: " << indexSpec
+ << "; normalized index specs: "
+ << BSON("normalSpecs" << normalSpecs));
+ auto indexCatalog = indexCollection->getIndexCatalog();
+ auto prepareSpecResult = indexCatalog->prepareSpecForCreate(opCtx, normalSpecs[0], {});
+ if (ErrorCodes::IndexBuildAlreadyInProgress == prepareSpecResult) {
+ LOGV2(4924900,
+ "Index build: already in progress during initial sync",
+ "ns"_attr = indexNss,
+ "uuid"_attr = indexCollection->uuid(),
+ "spec"_attr = indexSpec);
+ return;
+ }
+ }
+
// TODO(SERVER-48593): Add invariant on shouldRelaxIndexConstraints(opCtx, indexNss) and
// set constraints to kRelax.
const auto constraints =
@@ -205,7 +229,6 @@ void createIndexForApplyOps(OperationContext* opCtx,
// stop using ghost timestamps. Single phase builds are only used for empty collections, and
// to rebuild indexes admin.system collections. See SERVER-47439.
IndexBuildsCoordinator::updateCurOpOpDescription(opCtx, indexNss, {indexSpec});
- auto indexBuildsCoordinator = IndexBuildsCoordinator::get(opCtx);
auto collUUID = indexCollection->uuid();
auto fromMigrate = false;
indexBuildsCoordinator->createIndex(opCtx, collUUID, indexSpec, constraints, fromMigrate);