summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2019-03-06 14:19:10 -0500
committerBenety Goh <benety@mongodb.com>2019-03-06 14:19:10 -0500
commit2cc9b94ea266c87f7a71a708a108ce4f2466b76c (patch)
tree5429b5d7c31f5abfe9e685c12050e143f9602c2d /src/mongo
parentd0265ef8ba219d8ebaf703bcec45ab232fd90024 (diff)
downloadmongo-2cc9b94ea266c87f7a71a708a108ce4f2466b76c.tar.gz
SERVER-39085 IndexBuildsManager supports relaxing index constraints during index builds
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/catalog/index_builds_manager.cpp13
-rw-r--r--src/mongo/db/catalog/index_builds_manager.h16
-rw-r--r--src/mongo/db/catalog/index_builds_manager_test.cpp3
-rw-r--r--src/mongo/db/index_builder.h2
-rw-r--r--src/mongo/db/index_builds_coordinator.cpp48
5 files changed, 54 insertions, 28 deletions
diff --git a/src/mongo/db/catalog/index_builds_manager.cpp b/src/mongo/db/catalog/index_builds_manager.cpp
index a9e1bbee205..e016e0538d9 100644
--- a/src/mongo/db/catalog/index_builds_manager.cpp
+++ b/src/mongo/db/catalog/index_builds_manager.cpp
@@ -69,6 +69,8 @@ std::string toSummary(const std::map<UUID, std::shared_ptr<MultiIndexBlock>>& bu
} // namespace
+IndexBuildsManager::SetupOptions::SetupOptions() = default;
+
IndexBuildsManager::~IndexBuildsManager() {
invariant(_builders.empty(),
str::stream() << "Index builds still active: " << toSummary(_builders));
@@ -79,7 +81,7 @@ Status IndexBuildsManager::setUpIndexBuild(OperationContext* opCtx,
const std::vector<BSONObj>& specs,
const UUID& buildUUID,
OnInitFn onInit,
- bool forRecovery) {
+ SetupOptions options) {
_registerIndexBuild(buildUUID);
const auto& nss = collection->ns();
@@ -90,6 +92,13 @@ Status IndexBuildsManager::setUpIndexBuild(OperationContext* opCtx,
auto builder = _getBuilder(buildUUID);
+ // Ignore uniqueness constraint violations when relaxed (on secondaries). Secondaries can
+ // complete index builds in the middle of batches, which creates the potential for finding
+ // duplicate key violations where there otherwise would be none at consistent states.
+ if (options.indexConstraints == IndexConstraints::kRelax) {
+ builder->ignoreUniqueConstraint();
+ }
+
auto initResult = writeConflictRetry(opCtx,
"IndexBuildsManager::setUpIndexBuild",
nss.ns(),
@@ -101,7 +110,7 @@ Status IndexBuildsManager::setUpIndexBuild(OperationContext* opCtx,
return initResult.getStatus();
}
- if (forRecovery) {
+ if (options.forRecovery) {
log() << "Index build initialized: " << buildUUID << ": " << nss
<< ": indexes: " << initResult.getValue().size();
} else {
diff --git a/src/mongo/db/catalog/index_builds_manager.h b/src/mongo/db/catalog/index_builds_manager.h
index 255fdeba875..e2f23ad4bb6 100644
--- a/src/mongo/db/catalog/index_builds_manager.h
+++ b/src/mongo/db/catalog/index_builds_manager.h
@@ -56,6 +56,20 @@ class IndexBuildsManager {
MONGO_DISALLOW_COPYING(IndexBuildsManager);
public:
+ /**
+ * Indicates whether or not to ignore indexing constraints.
+ */
+ enum class IndexConstraints { kEnforce, kRelax };
+
+ /**
+ * Additional options for setUpIndexBuild. The default values are sufficient in most cases.
+ */
+ struct SetupOptions {
+ SetupOptions();
+ IndexConstraints indexConstraints = IndexConstraints::kEnforce;
+ bool forRecovery = false;
+ };
+
IndexBuildsManager() = default;
~IndexBuildsManager();
@@ -68,7 +82,7 @@ public:
const std::vector<BSONObj>& specs,
const UUID& buildUUID,
OnInitFn onInit,
- bool forRecovery);
+ SetupOptions options = {});
/**
* Recovers the index build from its persisted state and sets it up to run again.
diff --git a/src/mongo/db/catalog/index_builds_manager_test.cpp b/src/mongo/db/catalog/index_builds_manager_test.cpp
index c9820fafd15..3ecb5dca2a1 100644
--- a/src/mongo/db/catalog/index_builds_manager_test.cpp
+++ b/src/mongo/db/catalog/index_builds_manager_test.cpp
@@ -90,8 +90,7 @@ TEST_F(IndexBuildsManagerTest, IndexBuildsManagerSetUpAndTearDown) {
autoColl.getCollection(),
specs,
_buildUUID,
- MultiIndexBlock::kNoopOnInitFn,
- /*forRecovery=*/false));
+ MultiIndexBlock::kNoopOnInitFn));
_indexBuildsManager.tearDownIndexBuild(
operationContext(), autoColl.getCollection(), _buildUUID);
diff --git a/src/mongo/db/index_builder.h b/src/mongo/db/index_builder.h
index 8bb455aef0c..e90815ec510 100644
--- a/src/mongo/db/index_builder.h
+++ b/src/mongo/db/index_builder.h
@@ -70,7 +70,7 @@ class OperationContext;
class IndexBuilder : public BackgroundJob {
public:
/**
- * Indicates whether or not to ignore indexing errors.
+ * Indicates whether or not to ignore indexing constraints.
*/
enum class IndexConstraints { kEnforce, kRelax };
diff --git a/src/mongo/db/index_builds_coordinator.cpp b/src/mongo/db/index_builds_coordinator.cpp
index 7c6e82917e2..0923210b8ab 100644
--- a/src/mongo/db/index_builds_coordinator.cpp
+++ b/src/mongo/db/index_builds_coordinator.cpp
@@ -244,12 +244,10 @@ StatusWith<std::pair<long long, long long>> IndexBuildsCoordinator::startIndexRe
indexCatalogStats.numIndexesBefore =
_getNumIndexesTotal(opCtx, collection.get()) + indexNames.size();
- status = _indexBuildsManager.setUpIndexBuild(opCtx,
- collection.get(),
- specs,
- buildUUID,
- MultiIndexBlock::kNoopOnInitFn,
- /*forRecovery=*/true);
+ IndexBuildsManager::SetupOptions options;
+ options.forRecovery = true;
+ status = _indexBuildsManager.setUpIndexBuild(
+ opCtx, collection.get(), specs, buildUUID, MultiIndexBlock::kNoopOnInitFn, options);
if (!status.isOK()) {
// An index build failure during recovery is fatal.
logFailure(status, nss, replIndexBuildState);
@@ -611,25 +609,31 @@ IndexBuildsCoordinator::_registerAndSetUpIndexBuild(
onInitFn = MultiIndexBlock::makeTimestampedIndexOnInitFn(opCtx, collection);
}
- status = _indexBuildsManager.setUpIndexBuild(opCtx,
- collection,
- filteredSpecs,
- replIndexBuildState->buildUUID,
- onInitFn,
- /*forRecovery=*/false);
- if (!status.isOK()) {
- // Unregister the index build before setting the promise, so callers do not see the
- // build
- // again.
- _unregisterIndexBuild(lk, replIndexBuildState);
+ IndexBuildsManager::SetupOptions options;
+ options.indexConstraints =
+ repl::ReplicationCoordinator::get(opCtx)->shouldRelaxIndexConstraints(opCtx, nss)
+ ? IndexBuildsManager::IndexConstraints::kRelax
+ : IndexBuildsManager::IndexConstraints::kEnforce;
+ status = _indexBuildsManager.setUpIndexBuild(
+ opCtx, collection, filteredSpecs, replIndexBuildState->buildUUID, onInitFn, options);
+
+ // Indexes are present in the catalog in an unfinished state. Return an uninitialized
+ // Future so that the caller will continue building the indexes by calling _runIndexBuild().
+ // The completion of the index build will be communicated via a Future obtained from
+ // 'replIndexBuildState->sharedPromise'.
+ if (status.isOK()) {
+ return boost::none;
+ }
- // Set the promise in case another thread already joined the index build.
- replIndexBuildState->sharedPromise.setError(status);
+ _indexBuildsManager.tearDownIndexBuild(opCtx, collection, replIndexBuildState->buildUUID);
- return status;
- }
+ // Unregister the index build before setting the promise, so callers do not see the build again.
+ _unregisterIndexBuild(lk, replIndexBuildState);
+
+ // Set the promise in case another thread already joined the index build.
+ replIndexBuildState->sharedPromise.setError(status);
- return boost::none;
+ return status;
}
void IndexBuildsCoordinator::_runIndexBuild(OperationContext* opCtx,