diff options
author | Benety Goh <benety@mongodb.com> | 2019-03-06 14:19:10 -0500 |
---|---|---|
committer | Benety Goh <benety@mongodb.com> | 2019-03-06 14:19:10 -0500 |
commit | 2cc9b94ea266c87f7a71a708a108ce4f2466b76c (patch) | |
tree | 5429b5d7c31f5abfe9e685c12050e143f9602c2d /src/mongo | |
parent | d0265ef8ba219d8ebaf703bcec45ab232fd90024 (diff) | |
download | mongo-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.cpp | 13 | ||||
-rw-r--r-- | src/mongo/db/catalog/index_builds_manager.h | 16 | ||||
-rw-r--r-- | src/mongo/db/catalog/index_builds_manager_test.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/index_builder.h | 2 | ||||
-rw-r--r-- | src/mongo/db/index_builds_coordinator.cpp | 48 |
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, |