diff options
author | Dianna Hohensee <dianna.hohensee@mongodb.com> | 2019-10-04 13:42:44 +0000 |
---|---|---|
committer | evergreen <evergreen@mongodb.com> | 2019-10-04 13:42:44 +0000 |
commit | 20a03a3b3c96f54c5ec94a0eac8dcef768e39f43 (patch) | |
tree | 3ea3786f6db8a3d70f80ccfcb9109ee8ab358f14 | |
parent | d1c6b36bf04dd90ad963ad5dfbfa491de0c88789 (diff) | |
download | mongo-20a03a3b3c96f54c5ec94a0eac8dcef768e39f43.tar.gz |
SERVER-43711 ValidateAdaptor::validateIndexKeyCount should not compare in-memory and PIT _id index entry counts
-rw-r--r-- | src/mongo/db/catalog/collection_validation.cpp | 5 | ||||
-rw-r--r-- | src/mongo/db/catalog/index_consistency.h | 3 | ||||
-rw-r--r-- | src/mongo/db/catalog/validate_adaptor.cpp | 35 | ||||
-rw-r--r-- | src/mongo/db/catalog/validate_adaptor.h | 19 |
4 files changed, 29 insertions, 33 deletions
diff --git a/src/mongo/db/catalog/collection_validation.cpp b/src/mongo/db/catalog/collection_validation.cpp index ae13c779c3f..7be8c43723e 100644 --- a/src/mongo/db/catalog/collection_validation.cpp +++ b/src/mongo/db/catalog/collection_validation.cpp @@ -226,10 +226,7 @@ void _validateIndexKeyCount(OperationContext* opCtx, ValidateResults& curIndexResults = (*indexNsResultsMap)[descriptor->indexName()]; if (curIndexResults.valid) { - indexValidator->validateIndexKeyCount( - descriptor, - validateState->getCollection()->getRecordStore()->numRecords(opCtx), - curIndexResults); + indexValidator->validateIndexKeyCount(descriptor, curIndexResults); } } } diff --git a/src/mongo/db/catalog/index_consistency.h b/src/mongo/db/catalog/index_consistency.h index 78556234b94..472025e6e0b 100644 --- a/src/mongo/db/catalog/index_consistency.h +++ b/src/mongo/db/catalog/index_consistency.h @@ -30,11 +30,8 @@ #pragma once #include "mongo/bson/simple_bsonobj_comparator.h" -#include "mongo/db/catalog/collection_validation.h" -#include "mongo/db/catalog/throttle_cursor.h" #include "mongo/db/catalog/validate_state.h" #include "mongo/db/storage/key_string.h" -#include "mongo/db/storage/record_store.h" namespace mongo { diff --git a/src/mongo/db/catalog/validate_adaptor.cpp b/src/mongo/db/catalog/validate_adaptor.cpp index 7d43c3edc13..524719dd5c4 100644 --- a/src/mongo/db/catalog/validate_adaptor.cpp +++ b/src/mongo/db/catalog/validate_adaptor.cpp @@ -37,12 +37,14 @@ #include "mongo/db/catalog/collection.h" #include "mongo/db/catalog/index_catalog.h" #include "mongo/db/catalog/index_consistency.h" +#include "mongo/db/catalog/throttle_cursor.h" #include "mongo/db/index/index_access_method.h" #include "mongo/db/index/index_descriptor.h" #include "mongo/db/index/wildcard_access_method.h" #include "mongo/db/matcher/expression.h" #include "mongo/db/operation_context.h" #include "mongo/db/storage/key_string.h" +#include "mongo/db/storage/record_store.h" #include "mongo/rpc/object_check.h" #include "mongo/util/log.h" @@ -210,7 +212,7 @@ void ValidateAdaptor::traverseIndex(OperationContext* opCtx, void ValidateAdaptor::traverseRecordStore(OperationContext* opCtx, ValidateResults* results, BSONObjBuilder* output) { - long long nrecords = 0; + _numRecords = 0; // need to reset it because this function can be called more than once. long long dataSizeTotal = 0; long long interruptIntervalNumBytes = 0; long long nInvalid = 0; @@ -224,9 +226,9 @@ void ValidateAdaptor::traverseRecordStore(OperationContext* opCtx, traverseRecordStoreCursor->seekExact(opCtx, _validateState->getFirstRecordId()); record; record = traverseRecordStoreCursor->next(opCtx)) { - ++nrecords; + ++_numRecords; interruptIntervalNumBytes += record->data.size(); - if (nrecords % kInterruptIntervalNumRecords == 0 || + if (_numRecords % kInterruptIntervalNumRecords == 0 || interruptIntervalNumBytes >= kInterruptIntervalNumBytes) { opCtx->checkForInterrupt(); @@ -281,29 +283,29 @@ void ValidateAdaptor::traverseRecordStore(OperationContext* opCtx, // checkpoint and it may not have the most up-to-date changes. if (results->valid && !_validateState->isBackground()) { _validateState->getCollection()->getRecordStore()->updateStatsAfterRepair( - opCtx, nrecords, dataSizeTotal); + opCtx, _numRecords, dataSizeTotal); } output->appendNumber("nInvalidDocuments", nInvalid); - output->appendNumber("nrecords", nrecords); + output->appendNumber("nrecords", _numRecords); } -void ValidateAdaptor::validateIndexKeyCount(const IndexDescriptor* idx, - int64_t numRecs, - ValidateResults& results) { +void ValidateAdaptor::validateIndexKeyCount(const IndexDescriptor* idx, ValidateResults& results) { + // Fetch the total number of index entries we previously found traversing the index. const std::string indexName = idx->indexName(); IndexInfo* indexInfo = &_indexConsistency->getIndexInfo(indexName); auto numTotalKeys = indexInfo->numKeys; + // Do not fail on finding too few index entries compared to collection entries when full:false. bool hasTooFewKeys = false; bool noErrorOnTooFewKeys = !_validateState->isFullValidate(); - if (idx->isIdIndex() && numTotalKeys != numRecs) { - hasTooFewKeys = numTotalKeys < numRecs ? true : hasTooFewKeys; + if (idx->isIdIndex() && numTotalKeys != _numRecords) { + hasTooFewKeys = numTotalKeys < _numRecords ? true : hasTooFewKeys; std::string msg = str::stream() << "number of _id index entries (" << numTotalKeys - << ") does not match the number of documents in the index (" << numRecs << ")"; - if (noErrorOnTooFewKeys && (numTotalKeys < numRecs)) { + << ") does not match the number of documents in the index (" << _numRecords << ")"; + if (noErrorOnTooFewKeys && (numTotalKeys < _numRecords)) { results.warnings.push_back(msg); } else { results.errors.push_back(msg); @@ -316,21 +318,22 @@ void ValidateAdaptor::validateIndexKeyCount(const IndexDescriptor* idx, // produce an index key per array entry) and not $** indexes which can produce index keys for // multiple paths within a single document. if (results.valid && !idx->isMultikey() && idx->getIndexType() != IndexType::INDEX_WILDCARD && - numTotalKeys > numRecs) { + numTotalKeys > _numRecords) { std::string err = str::stream() << "index " << idx->indexName() << " is not multi-key, but has more entries (" - << numTotalKeys << ") than documents in the index (" << numRecs << ")"; + << numTotalKeys << ") than documents in the index (" << _numRecords << ")"; results.errors.push_back(err); results.valid = false; } + // Ignore any indexes with a special access method. If an access method name is given, the // index may be a full text, geo or special index plugin with different semantics. if (results.valid && !idx->isSparse() && !idx->isPartial() && !idx->isIdIndex() && - idx->getAccessMethodName() == "" && numTotalKeys < numRecs) { + idx->getAccessMethodName() == "" && numTotalKeys < _numRecords) { hasTooFewKeys = true; std::string msg = str::stream() << "index " << idx->indexName() << " is not sparse or partial, but has fewer entries (" - << numTotalKeys << ") than documents in the index (" << numRecs << ")"; + << numTotalKeys << ") than documents in the index (" << _numRecords << ")"; if (noErrorOnTooFewKeys) { results.warnings.push_back(msg); } else { diff --git a/src/mongo/db/catalog/validate_adaptor.h b/src/mongo/db/catalog/validate_adaptor.h index b68a6f37618..c035cb167e0 100644 --- a/src/mongo/db/catalog/validate_adaptor.h +++ b/src/mongo/db/catalog/validate_adaptor.h @@ -29,11 +29,7 @@ #pragma once -#include "mongo/db/catalog/collection_validation.h" -#include "mongo/db/catalog/throttle_cursor.h" #include "mongo/db/catalog/validate_state.h" -#include "mongo/db/storage/record_store.h" -#include "mongo/db/storage/sorted_data_interface.h" namespace mongo { @@ -42,8 +38,8 @@ class IndexDescriptor; class OperationContext; /** - * The record store validate adaptor is used to keep track of the index consistency during - * a validation that's running. + * The validate adaptor is used to keep track of collection and index consistency during a running + * collection validation operation. */ class ValidateAdaptor { using ValidateResultsMap = std::map<std::string, ValidateResults>; @@ -84,15 +80,18 @@ public: BSONObjBuilder* output); /** - * Validate that the number of document keys matches the number of index keys. + * Validates that the number of document keys matches the number of index keys previously + * traversed in traverseIndex(). */ - void validateIndexKeyCount(const IndexDescriptor* idx, - int64_t numRecs, - ValidateResults& results); + void validateIndexKeyCount(const IndexDescriptor* idx, ValidateResults& results); private: IndexConsistency* _indexConsistency; CollectionValidation::ValidateState* _validateState; ValidateResultsMap* _indexNsResultsMap; + + // Saves the record count from the record store traversal to be used later to validate the index + // entries count. Reset every time traverseRecordStore() is called. + long long _numRecords = 0; }; } // namespace mongo |