diff options
Diffstat (limited to 'src/mongo/db/index/index_access_method.cpp')
| -rw-r--r-- | src/mongo/db/index/index_access_method.cpp | 157 |
1 files changed, 36 insertions, 121 deletions
diff --git a/src/mongo/db/index/index_access_method.cpp b/src/mongo/db/index/index_access_method.cpp index 4d454f2b5a3..63148efb8cf 100644 --- a/src/mongo/db/index/index_access_method.cpp +++ b/src/mongo/db/index/index_access_method.cpp @@ -31,7 +31,7 @@ #include "mongo/platform/basic.h" -#include "mongo/db/index/index_access_method.h" +#include "mongo/db/index/btree_access_method.h" #include <utility> #include <vector> @@ -42,17 +42,10 @@ #include "mongo/db/catalog/index_consistency.h" #include "mongo/db/client.h" #include "mongo/db/commands/server_status.h" -#include "mongo/db/concurrency/exception_util.h" +#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/curop.h" -#include "mongo/db/index/2d_access_method.h" -#include "mongo/db/index/btree_access_method.h" -#include "mongo/db/index/fts_access_method.h" -#include "mongo/db/index/hash_access_method.h" #include "mongo/db/index/index_build_interceptor.h" #include "mongo/db/index/index_descriptor.h" -#include "mongo/db/index/s2_access_method.h" -#include "mongo/db/index/s2_bucket_access_method.h" -#include "mongo/db/index/wildcard_access_method.h" #include "mongo/db/jsobj.h" #include "mongo/db/keypattern.h" #include "mongo/db/operation_context.h" @@ -60,7 +53,6 @@ #include "mongo/db/repl/timestamp_block.h" #include "mongo/db/sorter/sorter.h" #include "mongo/db/storage/execution_context.h" -#include "mongo/db/storage/kv/kv_engine.h" #include "mongo/db/storage/storage_options.h" #include "mongo/logv2/log.h" #include "mongo/platform/atomic_word.h" @@ -79,35 +71,6 @@ MONGO_FAIL_POINT_DEFINE(hangIndexBuildDuringBulkLoadPhaseSecond); MONGO_FAIL_POINT_DEFINE(hangDuringIndexBuildBulkLoadYield); MONGO_FAIL_POINT_DEFINE(hangDuringIndexBuildBulkLoadYieldSecond); -/** - * Static factory method that constructs and returns an appropriate IndexAccessMethod depending on - * the type of the index. - */ -std::unique_ptr<IndexAccessMethod> IndexAccessMethod::make( - IndexCatalogEntry* entry, std::unique_ptr<SortedDataInterface> sortedDataInterface) { - auto desc = entry->descriptor(); - const std::string& type = desc->getAccessMethodName(); - if ("" == type) - return std::make_unique<BtreeAccessMethod>(entry, std::move(sortedDataInterface)); - else if (IndexNames::HASHED == type) - return std::make_unique<HashAccessMethod>(entry, std::move(sortedDataInterface)); - else if (IndexNames::GEO_2DSPHERE == type) - return std::make_unique<S2AccessMethod>(entry, std::move(sortedDataInterface)); - else if (IndexNames::GEO_2DSPHERE_BUCKET == type) - return std::make_unique<S2BucketAccessMethod>(entry, std::move(sortedDataInterface)); - else if (IndexNames::TEXT == type) - return std::make_unique<FTSAccessMethod>(entry, std::move(sortedDataInterface)); - else if (IndexNames::GEO_2D == type) - return std::make_unique<TwoDAccessMethod>(entry, std::move(sortedDataInterface)); - else if (IndexNames::WILDCARD == type) - return std::make_unique<WildcardAccessMethod>(entry, std::move(sortedDataInterface)); - LOGV2(20688, - "Can't find index for keyPattern {keyPattern}", - "Can't find index for keyPattern", - "keyPattern"_attr = desc->keyPattern()); - fassertFailed(31021); -} - namespace { /** @@ -136,10 +99,6 @@ public: builder.append("resumed", resumed.loadRelaxed()); builder.append("filesOpenedForExternalSort", sorterFileStats.opened.loadRelaxed()); builder.append("filesClosedForExternalSort", sorterFileStats.closed.loadRelaxed()); - builder.append("spilledRanges", sorterTracker.spilledRanges.loadRelaxed()); - builder.append("bytesSpilledUncompressed", - sorterTracker.bytesSpilledUncompressed.loadRelaxed()); - builder.append("bytesSpilled", sorterTracker.bytesSpilled.loadRelaxed()); return builder.obj(); } @@ -150,15 +109,11 @@ public: // This value should not exceed 'count'. AtomicWord<long long> resumed; - // Sorter statistics that are aggregate of all sorters. - SorterTracker sorterTracker; - // Number of times the external sorter opened/closed a file handle to spill data to disk. // This pair of counters in aggregate indicate the number of open file handles used by // the external sorter and may be useful in diagnosing situations where the process is // close to exhausting this finite resource. - SorterFileStats sorterFileStats = {&sorterTracker}; - + SorterFileStats sorterFileStats; } indexBulkBuilderSSS; /** @@ -177,9 +132,7 @@ SortOptions makeSortOptions(size_t maxMemoryUsageBytes, StringData dbName) { .TempDir(storageGlobalParams.dbpath + "/_tmp") .ExtSortAllowed() .MaxMemoryUsageBytes(maxMemoryUsageBytes) - .UseMemoryPool(true) .FileStats(&indexBulkBuilderSSS.sorterFileStats) - .Tracker(&indexBulkBuilderSSS.sorterTracker) .DBName(dbName.toString()); } @@ -412,13 +365,6 @@ void SortedDataIndexAccessMethod::removeOneKey(OperationContext* opCtx, try { _newInterface->unindex(opCtx, keyString, dupsAllowed); } catch (AssertionException& e) { - if (e.code() == ErrorCodes::DataCorruptionDetected) { - // DataCorruptionDetected errors are expected to have logged an error and added an entry - // to the health log with the stack trace at the location where the error was initially - // thrown. No need to do so again. - throw; - } - NamespaceString ns = _indexCatalogEntry->getNSSFromCatalog(opCtx); LOGV2(20683, "Assertion failure: _unindex failed on: {namespace} for index: {indexName}. " @@ -500,13 +446,9 @@ RecordId SortedDataIndexAccessMethod::findSingle(OperationContext* opCtx, void SortedDataIndexAccessMethod::validate(OperationContext* opCtx, int64_t* numKeys, IndexValidateResults* fullResults) const { - if (numKeys) { - long long keys = 0; - _newInterface->fullValidate(opCtx, &keys, fullResults); - *numKeys = keys; - } else { - _newInterface->fullValidate(opCtx, nullptr, fullResults); - } + long long keys = 0; + _newInterface->fullValidate(opCtx, &keys, fullResults); + *numKeys = keys; } bool SortedDataIndexAccessMethod::appendCustomStats(OperationContext* opCtx, @@ -638,8 +580,7 @@ Status SortedDataIndexAccessMethod::doUpdate(OperationContext* opCtx, // Add all new data keys into the index. for (const auto& keyString : ticket.added) { - bool dupsAllowed = (!_descriptor->prepareUnique() || !opCtx->isEnforcingConstraints()) && - ticket.dupsAllowed; + bool dupsAllowed = !_descriptor->prepareUnique() && ticket.dupsAllowed; auto status = _newInterface->insert(opCtx, keyString, dupsAllowed); if (!status.isOK()) return status; @@ -668,23 +609,6 @@ Ident* SortedDataIndexAccessMethod::getIdentPtr() const { return this->_newInterface.get(); } -void IndexAccessMethod::BulkBuilder::countNewBuildInStats() { - indexBulkBuilderSSS.count.addAndFetch(1); -} - -void IndexAccessMethod::BulkBuilder::countResumedBuildInStats() { - indexBulkBuilderSSS.count.addAndFetch(1); - indexBulkBuilderSSS.resumed.addAndFetch(1); -} - -SorterFileStats* IndexAccessMethod::BulkBuilder::bulkBuilderFileStats() { - return &indexBulkBuilderSSS.sorterFileStats; -} - -SorterTracker* IndexAccessMethod::BulkBuilder::bulkBuilderTracker() { - return &indexBulkBuilderSSS.sorterTracker; -} - class SortedDataIndexAccessMethod::BulkBuilderImpl final : public IndexAccessMethod::BulkBuilder { public: using Sorter = mongo::Sorter<KeyString::Value, mongo::NullValue>; @@ -700,6 +624,7 @@ public: Status insert(OperationContext* opCtx, const CollectionPtr& collection, + SharedBufferFragmentBuilder& pooledBuilder, const BSONObj& obj, const RecordId& loc, const InsertDeleteOptions& options, @@ -783,6 +708,7 @@ SortedDataIndexAccessMethod::BulkBuilderImpl::BulkBuilderImpl(SortedDataIndexAcc Status SortedDataIndexAccessMethod::BulkBuilderImpl::insert( OperationContext* opCtx, const CollectionPtr& collection, + SharedBufferFragmentBuilder& pooledBuilder, const BSONObj& obj, const RecordId& loc, const InsertDeleteOptions& options, @@ -796,7 +722,7 @@ Status SortedDataIndexAccessMethod::BulkBuilderImpl::insert( try { _iam->getKeys(opCtx, collection, - _sorter->memPool(), + pooledBuilder, obj, options.getKeysMode, GetKeysContext::kAddingKeys, @@ -917,23 +843,26 @@ void SortedDataIndexAccessMethod::BulkBuilderImpl::_yield(OperationContext* opCt auto locker = opCtx->lockState(); Locker::LockSnapshot snapshot; - locker->saveLockStateAndUnlock(&snapshot); - - // Track the number of yields in CurOp. - CurOp::get(opCtx)->yielded(); - - auto failPointHang = [opCtx, &ns](FailPoint* fp) { - fp->executeIf( - [fp](auto&&) { - LOGV2(5180600, "Hanging index build during bulk load yield"); - fp->pauseWhileSet(); - }, - [opCtx, &ns](auto&& config) { return config.getStringField("namespace") == ns.ns(); }); - }; - failPointHang(&hangDuringIndexBuildBulkLoadYield); - failPointHang(&hangDuringIndexBuildBulkLoadYieldSecond); - - locker->restoreLockState(opCtx, snapshot); + if (locker->saveLockStateAndUnlock(&snapshot)) { + + // Track the number of yields in CurOp. + CurOp::get(opCtx)->yielded(); + + auto failPointHang = [opCtx, &ns](FailPoint* fp) { + fp->executeIf( + [fp](auto&&) { + LOGV2(5180600, "Hanging index build during bulk load yield"); + fp->pauseWhileSet(); + }, + [opCtx, &ns](auto&& config) { + return config.getStringField("namespace") == ns.ns(); + }); + }; + failPointHang(&hangDuringIndexBuildBulkLoadYield); + failPointHang(&hangDuringIndexBuildBulkLoadYieldSecond); + + locker->restoreLockState(opCtx, snapshot); + } yieldable->restore(); } @@ -1215,16 +1144,6 @@ Status SortedDataIndexAccessMethod::_indexKeysOrWriteToSideTable( *keysInsertedOut += inserted; } } else { - // Ensure that our snapshot is compatible with the index's minimum visibile snapshot. - const auto minVisibleTimestamp = _indexCatalogEntry->getMinimumVisibleSnapshot(); - const auto readTimestamp = - opCtx->recoveryUnit()->getPointInTimeReadTimestamp(opCtx).value_or( - opCtx->recoveryUnit()->getCatalogConflictingTimestamp()); - if (minVisibleTimestamp && !readTimestamp.isNull() && - readTimestamp < *minVisibleTimestamp) { - throw WriteConflictException(); - } - int64_t numInserted = 0; status = insertKeysAndUpdateMultikeyPaths( opCtx, @@ -1280,16 +1199,12 @@ void SortedDataIndexAccessMethod::_unindexKeysOrWriteToSideTable( // are allowed in unique indexes, WiredTiger does not do blind unindexing, and instead confirms // that the recordid matches the element we are removing. // - // We need to disable blind-deletes if 'checkRecordId' is explicitly set 'On'. - options.dupsAllowed = options.dupsAllowed || checkRecordId == CheckRecordId::On; - - // Ensure that our snapshot is compatible with the index's minimum visibile snapshot. - const auto minVisibleTimestamp = _indexCatalogEntry->getMinimumVisibleSnapshot(); - const auto readTimestamp = opCtx->recoveryUnit()->getPointInTimeReadTimestamp(opCtx).value_or( - opCtx->recoveryUnit()->getCatalogConflictingTimestamp()); - if (minVisibleTimestamp && !readTimestamp.isNull() && readTimestamp < *minVisibleTimestamp) { - throw WriteConflictException(); - } + // We need to disable blind-deletes if 'checkRecordId' is explicitly set 'On', or for + // in-progress indexes, in order to force recordid-matching for unindex operations, since + // initial sync can build an index over a collection with duplicates. See SERVER-17487 for more + // details. + options.dupsAllowed = options.dupsAllowed || !_indexCatalogEntry->isReady(opCtx) || + (checkRecordId == CheckRecordId::On); int64_t removed = 0; Status status = removeKeys(opCtx, keys, options, &removed); |
