diff options
Diffstat (limited to 'src/mongo/db/catalog')
-rw-r--r-- | src/mongo/db/catalog/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/catalog/collection_compact.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/catalog/database_test.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/catalog/index_build_block.cpp | 17 | ||||
-rw-r--r-- | src/mongo/db/catalog/index_catalog.h | 24 | ||||
-rw-r--r-- | src/mongo/db/catalog/index_catalog_entry.h | 2 | ||||
-rw-r--r-- | src/mongo/db/catalog/index_catalog_entry_impl.h | 2 | ||||
-rw-r--r-- | src/mongo/db/catalog/index_catalog_impl.cpp | 28 | ||||
-rw-r--r-- | src/mongo/db/catalog/index_catalog_impl.h | 6 | ||||
-rw-r--r-- | src/mongo/db/catalog/index_catalog_noop.h | 4 | ||||
-rw-r--r-- | src/mongo/db/catalog/multi_index_block.cpp | 104 | ||||
-rw-r--r-- | src/mongo/db/catalog/multi_index_block.h | 29 | ||||
-rw-r--r-- | src/mongo/db/catalog/multi_index_block.idl | 9 |
13 files changed, 151 insertions, 79 deletions
diff --git a/src/mongo/db/catalog/SConscript b/src/mongo/db/catalog/SConscript index aa207774bc4..1d1a5868aae 100644 --- a/src/mongo/db/catalog/SConscript +++ b/src/mongo/db/catalog/SConscript @@ -249,6 +249,7 @@ env.Library( ], LIBDEPS_PRIVATE=[ '$BUILD_DIR/mongo/db/index/index_build_interceptor', + '$BUILD_DIR/mongo/db/storage/storage_options', '$BUILD_DIR/mongo/idl/server_parameter', ] ) diff --git a/src/mongo/db/catalog/collection_compact.cpp b/src/mongo/db/catalog/collection_compact.cpp index 6170ac334d1..cb5e854c11a 100644 --- a/src/mongo/db/catalog/collection_compact.cpp +++ b/src/mongo/db/catalog/collection_compact.cpp @@ -118,7 +118,6 @@ StatusWith<CompactStats> compactCollection(OperationContext* opCtx, CompactStats stats; MultiIndexBlock indexer(opCtx, collection); - indexer.allowInterruption(); indexer.ignoreUniqueConstraint(); // in compact we should be doing no checking Status status = indexer.init(indexSpecs).getStatus(); diff --git a/src/mongo/db/catalog/database_test.cpp b/src/mongo/db/catalog/database_test.cpp index 0e0205a0380..2237571c7e6 100644 --- a/src/mongo/db/catalog/database_test.cpp +++ b/src/mongo/db/catalog/database_test.cpp @@ -308,7 +308,8 @@ void _testDropCollectionThrowsExceptionIfThereAreIndexesInProgress(OperationCont << "ns" << nss.ns()); - auto indexBuildBlock = indexCatalog->createIndexBuildBlock(opCtx, indexInfoObj); + auto indexBuildBlock = + indexCatalog->createIndexBuildBlock(opCtx, indexInfoObj, IndexBuildMethod::kHybrid); { WriteUnitOfWork wuow(opCtx); ASSERT_OK(indexBuildBlock->init()); diff --git a/src/mongo/db/catalog/index_build_block.cpp b/src/mongo/db/catalog/index_build_block.cpp index 270b2f2d12b..51294456a36 100644 --- a/src/mongo/db/catalog/index_build_block.cpp +++ b/src/mongo/db/catalog/index_build_block.cpp @@ -49,11 +49,13 @@ namespace mongo { IndexCatalogImpl::IndexBuildBlock::IndexBuildBlock(OperationContext* opCtx, Collection* collection, IndexCatalogImpl* catalog, - const BSONObj& spec) + const BSONObj& spec, + IndexBuildMethod method) : _collection(collection), _catalog(catalog), _ns(_collection->ns().ns()), _spec(spec.getOwned()), + _method(method), _entry(nullptr), _opCtx(opCtx) { invariant(collection); @@ -71,7 +73,8 @@ Status IndexCatalogImpl::IndexBuildBlock::init() { _indexName = descriptor->indexName(); _indexNamespace = descriptor->indexNamespace(); - bool isBackgroundIndex = _spec["background"].trueValue(); + bool isBackgroundIndex = + _method == IndexBuildMethod::kHybrid || _method == IndexBuildMethod::kBackground; bool isBackgroundSecondaryBuild = false; if (auto replCoord = repl::ReplicationCoordinator::get(_opCtx)) { isBackgroundSecondaryBuild = @@ -91,15 +94,7 @@ Status IndexCatalogImpl::IndexBuildBlock::init() { _entry = _catalog->_setupInMemoryStructures( _opCtx, std::move(descriptor), initFromDisk, isReadyIndex); - // Hybrid indexes are only enabled for background indexes. - bool useHybrid = true; - // TODO: Remove when SERVER-37270 is complete. - useHybrid = useHybrid && isBackgroundIndex; - // TODO: Remove when SERVER-38550 is complete. The mobile storage engine does not suport - // dupsAllowed mode on bulk builders. - useHybrid = useHybrid && storageGlobalParams.engine != "mobile"; - - if (useHybrid) { + if (_method == IndexBuildMethod::kHybrid) { _indexBuildInterceptor = stdx::make_unique<IndexBuildInterceptor>(_opCtx, _entry); _entry->setIndexBuildInterceptor(_indexBuildInterceptor.get()); diff --git a/src/mongo/db/catalog/index_catalog.h b/src/mongo/db/catalog/index_catalog.h index e759efef753..55d5c79446a 100644 --- a/src/mongo/db/catalog/index_catalog.h +++ b/src/mongo/db/catalog/index_catalog.h @@ -54,6 +54,28 @@ struct BsonRecord { const BSONObj* docPtr; }; +enum class IndexBuildMethod { + /** + * Use a collection scan to dump all keys into an external sorter. During this process, + * concurrent client writes are accepted, and their generated keys are written into an + * interceptor. On completion, this interceptor is drained and used to verify uniqueness + * constraints on the index. + * + * This is the default for all index builds. + */ + kHybrid, + /** + * Perform a collection scan by writing each document's generated key directly into the index. + * Accept writes in the background into the index as well. + */ + kBackground, + /** + * Perform a collection scan to dump all keys into the exteral sorter, then into the index. + * During this process, callers guarantee that no writes will be accepted on this collection. + */ + kForeground, +}; + /** * The IndexCatalog is owned by the Collection and is responsible for the lookup and lifetimes of * the indexes in a collection. Every collection has exactly one instance of this class. @@ -429,7 +451,7 @@ public: * spex and OperationContext. */ virtual std::unique_ptr<IndexBuildBlockInterface> createIndexBuildBlock( - OperationContext* opCtx, const BSONObj& spec) = 0; + OperationContext* opCtx, const BSONObj& spec, IndexBuildMethod method) = 0; // public helpers diff --git a/src/mongo/db/catalog/index_catalog_entry.h b/src/mongo/db/catalog/index_catalog_entry.h index 1e52a6ac447..ef6628cfffc 100644 --- a/src/mongo/db/catalog/index_catalog_entry.h +++ b/src/mongo/db/catalog/index_catalog_entry.h @@ -75,7 +75,7 @@ public: virtual const IndexAccessMethod* accessMethod() const = 0; - virtual bool isBuilding() const = 0; + virtual bool isHybridBuilding() const = 0; virtual IndexBuildInterceptor* indexBuildInterceptor() = 0; diff --git a/src/mongo/db/catalog/index_catalog_entry_impl.h b/src/mongo/db/catalog/index_catalog_entry_impl.h index a5a53f2dff2..7460b765b34 100644 --- a/src/mongo/db/catalog/index_catalog_entry_impl.h +++ b/src/mongo/db/catalog/index_catalog_entry_impl.h @@ -90,7 +90,7 @@ public: return _accessMethod.get(); } - bool isBuilding() const final { + bool isHybridBuilding() const final { return _indexBuildInterceptor != nullptr; } diff --git a/src/mongo/db/catalog/index_catalog_impl.cpp b/src/mongo/db/catalog/index_catalog_impl.cpp index 02def7005d9..08498dd3d8b 100644 --- a/src/mongo/db/catalog/index_catalog_impl.cpp +++ b/src/mongo/db/catalog/index_catalog_impl.cpp @@ -310,7 +310,7 @@ StatusWith<BSONObj> IndexCatalogImpl::createIndexOnEmptyCollection(OperationCont spec = statusWithSpec.getValue(); // now going to touch disk - IndexBuildBlock indexBuildBlock(opCtx, _collection, this, spec); + IndexBuildBlock indexBuildBlock(opCtx, _collection, this, spec, IndexBuildMethod::kForeground); status = indexBuildBlock.init(); if (!status.isOK()) return status; @@ -1187,11 +1187,12 @@ Status IndexCatalogImpl::_indexFilteredRecords(OperationContext* opCtx, } Status status = Status::OK(); - if (index->isBuilding()) { + if (index->isHybridBuilding()) { int64_t inserted; status = index->indexBuildInterceptor()->sideWrite(opCtx, index->accessMethod(), bsonRecord.docPtr, + options, bsonRecord.id, IndexBuildInterceptor::Op::kInsert, &inserted); @@ -1237,10 +1238,19 @@ Status IndexCatalogImpl::_unindexRecord(OperationContext* opCtx, const RecordId& loc, bool logIfError, int64_t* keysDeletedOut) { - if (index->isBuilding()) { + InsertDeleteOptions options; + prepareInsertDeleteOptions(opCtx, index->descriptor(), &options); + options.logIfError = logIfError; + + if (index->isHybridBuilding()) { int64_t removed; - auto status = index->indexBuildInterceptor()->sideWrite( - opCtx, index->accessMethod(), &obj, loc, IndexBuildInterceptor::Op::kDelete, &removed); + auto status = index->indexBuildInterceptor()->sideWrite(opCtx, + index->accessMethod(), + &obj, + options, + loc, + IndexBuildInterceptor::Op::kDelete, + &removed); if (status.isOK() && keysDeletedOut) { *keysDeletedOut += removed; } @@ -1248,10 +1258,6 @@ Status IndexCatalogImpl::_unindexRecord(OperationContext* opCtx, return status; } - InsertDeleteOptions options; - prepareInsertDeleteOptions(opCtx, index->descriptor(), &options); - options.logIfError = logIfError; - // On WiredTiger, we do blind unindexing of records for efficiency. However, when duplicates // are allowed in unique indexes, WiredTiger does not do blind unindexing, and instead confirms // that the recordid matches the element we are removing. @@ -1399,8 +1405,8 @@ Status IndexCatalogImpl::compactIndexes(OperationContext* opCtx) { } std::unique_ptr<IndexCatalog::IndexBuildBlockInterface> IndexCatalogImpl::createIndexBuildBlock( - OperationContext* opCtx, const BSONObj& spec) { - return std::make_unique<IndexBuildBlock>(opCtx, _collection, this, spec); + OperationContext* opCtx, const BSONObj& spec, IndexBuildMethod method) { + return std::make_unique<IndexBuildBlock>(opCtx, _collection, this, spec, method); } std::string::size_type IndexCatalogImpl::getLongestIndexNameLength(OperationContext* opCtx) const { diff --git a/src/mongo/db/catalog/index_catalog_impl.h b/src/mongo/db/catalog/index_catalog_impl.h index da755206ba8..36d9e8c41e4 100644 --- a/src/mongo/db/catalog/index_catalog_impl.h +++ b/src/mongo/db/catalog/index_catalog_impl.h @@ -249,7 +249,8 @@ public: IndexBuildBlock(OperationContext* opCtx, Collection* collection, IndexCatalogImpl* catalog, - const BSONObj& spec); + const BSONObj& spec, + IndexBuildMethod method); ~IndexBuildBlock(); @@ -288,6 +289,7 @@ public: const std::string _ns; BSONObj _spec; + IndexBuildMethod _method; std::string _indexName; std::string _indexNamespace; @@ -336,7 +338,7 @@ public: } std::unique_ptr<IndexCatalog::IndexBuildBlockInterface> createIndexBuildBlock( - OperationContext* opCtx, const BSONObj& spec) override; + OperationContext* opCtx, const BSONObj& spec, IndexBuildMethod method) override; std::string::size_type getLongestIndexNameLength(OperationContext* opCtx) const override; diff --git a/src/mongo/db/catalog/index_catalog_noop.h b/src/mongo/db/catalog/index_catalog_noop.h index 4331d8f4afc..0806f98773e 100644 --- a/src/mongo/db/catalog/index_catalog_noop.h +++ b/src/mongo/db/catalog/index_catalog_noop.h @@ -206,8 +206,8 @@ public: return ""; } - std::unique_ptr<IndexBuildBlockInterface> createIndexBuildBlock(OperationContext* opCtx, - const BSONObj& spec) override { + std::unique_ptr<IndexBuildBlockInterface> createIndexBuildBlock( + OperationContext* opCtx, const BSONObj& spec, IndexBuildMethod method) override { return {}; } diff --git a/src/mongo/db/catalog/multi_index_block.cpp b/src/mongo/db/catalog/multi_index_block.cpp index b4fb4a481be..2dcfe29b4e3 100644 --- a/src/mongo/db/catalog/multi_index_block.cpp +++ b/src/mongo/db/catalog/multi_index_block.cpp @@ -51,6 +51,7 @@ #include "mongo/db/repl/repl_set_config.h" #include "mongo/db/repl/replication_coordinator.h" #include "mongo/db/server_parameters.h" +#include "mongo/db/storage/storage_options.h" #include "mongo/db/storage/write_unit_of_work.h" #include "mongo/logger/redaction.h" #include "mongo/util/assert_util.h" @@ -132,12 +133,16 @@ MultiIndexBlock::~MultiIndexBlock() { } } -void MultiIndexBlock::allowBackgroundBuilding() { - _buildInBackground = true; -} +bool MultiIndexBlock::areHybridIndexBuildsEnabled() { + // The mobile storage engine does not suport dupsAllowed mode on bulk builders, which means that + // it does not support hybrid builds. See SERVER-38550 + if (storageGlobalParams.engine == "mobile") { + return false; + } -void MultiIndexBlock::allowInterruption() { - _allowInterruption = true; + // TODO: SERVER-37272 Disable hybrid if in FCV 4.0. + + return enableHybridIndexBuilds.load(); } void MultiIndexBlock::ignoreUniqueConstraint() { @@ -183,11 +188,25 @@ StatusWith<std::vector<BSONObj>> MultiIndexBlock::init(const std::vector<BSONObj if (!status.isOK()) return status; + const bool enableHybrid = areHybridIndexBuildsEnabled(); + + // Parse the specs if this builder is not building hybrid indexes, otherwise log a message. for (size_t i = 0; i < indexSpecs.size(); i++) { BSONObj info = indexSpecs[i]; + if (enableHybrid) { + if (info["background"].isBoolean() && !info["background"].Bool()) { + log() << "ignoring obselete { background: false } index build option because all " + "indexes are built in the background with the hybrid method"; + } + continue; + } - // Any foreground indexes make all indexes be built in the foreground. - _buildInBackground = (_buildInBackground && info["background"].trueValue()); + // A single foreground build makes the entire builder foreground. + if (info["background"].trueValue() && _method != IndexBuildMethod::kForeground) { + _method = IndexBuildMethod::kBackground; + } else { + _method = IndexBuildMethod::kForeground; + } } std::vector<BSONObj> indexInfoObjs; @@ -210,7 +229,7 @@ StatusWith<std::vector<BSONObj>> MultiIndexBlock::init(const std::vector<BSONObj indexInfoObjs.push_back(info); IndexToBuild index; - index.block = _collection->getIndexCatalog()->createIndexBuildBlock(_opCtx, info); + index.block = _collection->getIndexCatalog()->createIndexBuildBlock(_opCtx, info, _method); status = index.block->init(); if (!status.isOK()) return status; @@ -220,9 +239,9 @@ StatusWith<std::vector<BSONObj>> MultiIndexBlock::init(const std::vector<BSONObj if (!status.isOK()) return status; - // Foreground builds and background builds using an interceptor can use the bulk builder. + // Hybrid builds and non-hybrid foreground builds use the bulk builder. const bool useBulk = - !_buildInBackground || index.block->getEntry()->indexBuildInterceptor(); + _method == IndexBuildMethod::kHybrid || _method == IndexBuildMethod::kForeground; if (useBulk) { // Bulk build process requires foreground building as it assumes nothing is changing // under it. @@ -233,16 +252,18 @@ StatusWith<std::vector<BSONObj>> MultiIndexBlock::init(const std::vector<BSONObj _collection->getIndexCatalog()->prepareInsertDeleteOptions( _opCtx, descriptor, &index.options); - // Allow duplicates when explicitly allowed or an interceptor is installed, which will - // perform duplicate checking itself. + + // Allow duplicates when explicitly allowed or when using hybrid builds, which will perform + // duplicate checking itself. index.options.dupsAllowed = index.options.dupsAllowed || _ignoreUnique || - index.block->getEntry()->indexBuildInterceptor(); + index.block->getEntry()->isHybridBuilding(); if (_ignoreUnique) { index.options.getKeysMode = IndexAccessMethod::GetKeysMode::kRelaxConstraints; } index.options.fromIndexBuilder = true; - log() << "index build: starting on " << ns << " properties: " << descriptor->toString(); + log() << "index build: starting on " << ns << " properties: " << descriptor->toString() + << " using method: " << _method; if (index.bulk) log() << "build may temporarily use up to " << eachIndexBuildMaxMemoryUsageBytes / 1024 / 1024 << " megabytes of RAM"; @@ -255,7 +276,7 @@ StatusWith<std::vector<BSONObj>> MultiIndexBlock::init(const std::vector<BSONObj _indexes.push_back(std::move(index)); } - if (_buildInBackground) + if (isBackgroundBuilding()) _backgroundOperation.reset(new BackgroundOperation(ns)); auto replCoord = repl::ReplicationCoordinator::get(_opCtx); @@ -321,8 +342,7 @@ Status MultiIndexBlock::insertAllDocumentsInCollection() { unsigned long long n = 0; PlanExecutor::YieldPolicy yieldPolicy; - if (_buildInBackground) { - invariant(_allowInterruption); + if (isBackgroundBuilding()) { yieldPolicy = PlanExecutor::YIELD_AUTO; } else { yieldPolicy = PlanExecutor::WRITE_CONFLICT_RETRY_ONLY; @@ -335,8 +355,9 @@ Status MultiIndexBlock::insertAllDocumentsInCollection() { // with every insert into the index, which resets the collection scan cursor between every call // to getNextSnapshotted(). With read-once cursors enabled, this can evict data we may need to // read again, incurring a significant performance penalty. - // TODO: Enable this for all index builds when SERVER-37268 is complete. - bool readOnce = !_buildInBackground && useReadOnceCursorsForIndexBuilds.load(); + // Note: This does not apply to hybrid builds because they write keys to the external sorter. + bool readOnce = + _method != IndexBuildMethod::kBackground && useReadOnceCursorsForIndexBuilds.load(); _opCtx->recoveryUnit()->setReadOnce(readOnce); Snapshotted<BSONObj> objToIndex; @@ -347,7 +368,8 @@ Status MultiIndexBlock::insertAllDocumentsInCollection() { (PlanExecutor::ADVANCED == (state = exec->getNextSnapshotted(&objToIndex, &loc))) || MONGO_FAIL_POINT(hangAfterStartingIndexBuild)) { try { - if (_allowInterruption && !_opCtx->checkForInterruptNoAssert().isOK()) + auto interruptStatus = _opCtx->checkForInterruptNoAssert(); + if (!interruptStatus.isOK()) return _opCtx->checkForInterruptNoAssert(); if (!retries && PlanExecutor::ADVANCED != state) { @@ -369,14 +391,14 @@ Status MultiIndexBlock::insertAllDocumentsInCollection() { WriteUnitOfWork wunit(_opCtx); Status ret = insert(objToIndex.value(), loc); - if (_buildInBackground) + if (_method == IndexBuildMethod::kBackground) exec->saveState(); if (!ret.isOK()) { // Fail the index build hard. return ret; } wunit.commit(); - if (_buildInBackground) { + if (_method == IndexBuildMethod::kBackground) { try { exec->restoreState(); // Handles any WCEs internally. } catch (...) { @@ -391,6 +413,10 @@ Status MultiIndexBlock::insertAllDocumentsInCollection() { n++; retries = 0; } catch (const WriteConflictException&) { + // Only background builds write inside transactions, and therefore should only ever + // generate WCEs. + invariant(_method == IndexBuildMethod::kBackground); + CurOp::get(_opCtx)->debug().additiveMetrics.incrementWriteConflicts(1); retries++; // logAndBackoff expects this to be 1 on first call. WriteConflictException::logAndBackoff( @@ -421,7 +447,7 @@ Status MultiIndexBlock::insertAllDocumentsInCollection() { "'hangAfterStartingIndexBuildUnlocked' failpoint"; MONGO_FAIL_POINT_PAUSE_WHILE_SET(hangAfterStartingIndexBuildUnlocked); - if (_buildInBackground) { + if (isBackgroundBuilding()) { _opCtx->lockState()->restoreLockState(_opCtx, lockInfo); _opCtx->recoveryUnit()->abandonSnapshot(); return Status(ErrorCodes::OperationFailed, @@ -435,7 +461,7 @@ Status MultiIndexBlock::insertAllDocumentsInCollection() { progress->finished(); log() << "index build: collection scan done. scanned " << n << " total records in " - << t.seconds() << " secs"; + << t.seconds() << " seconds"; Status ret = dumpInsertsFromBulk(); if (!ret.isOK()) @@ -500,13 +526,17 @@ Status MultiIndexBlock::dumpInsertsFromBulk(std::set<RecordId>* dupRecords) { // when 'dupRecords' is not used because these two vectors are mutually incompatible. std::vector<BSONObj> dupKeysInserted; + // When dupRecords is passed, 'dupsAllowed' should be passed to reflect whether or not the + // index is unique. + bool dupsAllowed = (dupRecords) ? !_indexes[i].block->getEntry()->descriptor()->unique() + : _indexes[i].options.dupsAllowed; + IndexCatalogEntry* entry = _indexes[i].block->getEntry(); LOG(1) << "index build: inserting from external sorter into index: " << entry->descriptor()->indexName(); Status status = _indexes[i].real->commitBulk(_opCtx, _indexes[i].bulk.get(), - _allowInterruption, - _indexes[i].options.dupsAllowed, + dupsAllowed, dupRecords, (dupRecords) ? nullptr : &dupKeysInserted); if (!status.isOK()) { @@ -532,7 +562,7 @@ Status MultiIndexBlock::dumpInsertsFromBulk(std::set<RecordId>* dupRecords) { return Status::OK(); } -Status MultiIndexBlock::drainBackgroundWritesIfNeeded() { +Status MultiIndexBlock::drainBackgroundWrites() { if (State::kAborted == _getState()) { return {ErrorCodes::IndexBuildAborted, str::stream() << "Index build aborted: " << _abortReason @@ -678,8 +708,8 @@ void MultiIndexBlock::abort(StringData reason) { } -bool MultiIndexBlock::getBuildInBackground() const { - return _buildInBackground; +bool MultiIndexBlock::isBackgroundBuilding() const { + return _method == IndexBuildMethod::kBackground || _method == IndexBuildMethod::kHybrid; } MultiIndexBlock::State MultiIndexBlock::getState_forTest() const { @@ -755,4 +785,20 @@ std::ostream& operator<<(std::ostream& os, const MultiIndexBlock::State& state) MONGO_UNREACHABLE; } +logger::LogstreamBuilder& operator<<(logger::LogstreamBuilder& out, + const IndexBuildMethod& method) { + switch (method) { + case IndexBuildMethod::kHybrid: + out.stream() << "Hybrid"; + break; + case IndexBuildMethod::kBackground: + out.stream() << "Background"; + break; + case IndexBuildMethod::kForeground: + out.stream() << "Foreground"; + break; + } + return out; +} + } // namespace mongo diff --git a/src/mongo/db/catalog/multi_index_block.h b/src/mongo/db/catalog/multi_index_block.h index 7b5b818ee06..525a193bfd5 100644 --- a/src/mongo/db/catalog/multi_index_block.h +++ b/src/mongo/db/catalog/multi_index_block.h @@ -71,21 +71,7 @@ public: MultiIndexBlock(OperationContext* opCtx, Collection* collection); ~MultiIndexBlock(); - /** - * By default we ignore the 'background' flag in specs when building an index. If this is - * called before init(), we will build the indexes in the background as long as *all* specs - * call for background indexing. If any spec calls for foreground indexing all indexes will - * be built in the foreground, as there is no concurrency benefit to building a subset of - * indexes in the background, but there is a performance benefit to building all in the - * foreground. - */ - void allowBackgroundBuilding(); - - /** - * Call this before init() to allow the index build to be interrupted. - * This only affects builds using the insertAllDocumentsInCollection helper. - */ - void allowInterruption(); + static bool areHybridIndexBuildsEnabled(); /** * By default we enforce the 'unique' flag in specs when building an index by failing. @@ -157,7 +143,7 @@ public: * * Must not be in a WriteUnitOfWork. */ - Status drainBackgroundWritesIfNeeded(); + Status drainBackgroundWrites(); /** * Check any constraits that may have been temporarily violated during the index build for @@ -225,7 +211,11 @@ public: */ void abortWithoutCleanup(); - bool getBuildInBackground() const; + /** + * Returns true if this build block supports background writes while building an index. This is + * true for the kHybrid and kBackground methods. + */ + bool isBackgroundBuilding() const; /** * State transitions: @@ -289,8 +279,8 @@ private: Collection* _collection; OperationContext* _opCtx; - bool _buildInBackground = false; - bool _allowInterruption = false; + IndexBuildMethod _method = IndexBuildMethod::kHybrid; + bool _ignoreUnique = false; bool _needToCleanup = true; @@ -306,4 +296,5 @@ private: // The ASSERT_*() macros use this function to print the value of 'state' when the predicate fails. std::ostream& operator<<(std::ostream& os, const MultiIndexBlock::State& state); +logger::LogstreamBuilder& operator<<(logger::LogstreamBuilder& out, const IndexBuildMethod& method); } // namespace mongo diff --git a/src/mongo/db/catalog/multi_index_block.idl b/src/mongo/db/catalog/multi_index_block.idl index 3d1d4a145d7..08b183e3560 100644 --- a/src/mongo/db/catalog/multi_index_block.idl +++ b/src/mongo/db/catalog/multi_index_block.idl @@ -42,6 +42,15 @@ server_parameters: cpp_vartype: AtomicWord<bool> default: true + enableHybridIndexBuilds: + description: "Build all indexes by performing external sorting while accepting concurrent client writes" + set_at: + - runtime + - startup + cpp_varname: enableHybridIndexBuilds + cpp_vartype: AtomicWord<bool> + default: true + maxIndexBuildMemoryUsageMegabytes: description: "Limits the amount of memory that simultaneous foreground index builds on one collection may consume for the duration of the builds" set_at: |