diff options
author | Dan Larkin-York <dan.larkin-york@mongodb.com> | 2023-01-30 22:17:36 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2023-02-10 03:46:06 +0000 |
commit | 7877b7785b5276fed86f17bd3dd2dd1a18ab0a97 (patch) | |
tree | b509f69c40be224e19a84e49e7decaeb2a9f55b7 | |
parent | 9a818736f42bd50a7349e61ef5f69d6fdc64924f (diff) | |
download | mongo-7877b7785b5276fed86f17bd3dd2dd1a18ab0a97.tar.gz |
SERVER-72677 Surface index validation errors arising from WT::verify
(cherry picked from commit 40c93f028e36f78c06756f4bfd358d240bdd9b34)
-rw-r--r-- | src/mongo/db/catalog/collection_validation.cpp | 21 | ||||
-rw-r--r-- | src/mongo/db/catalog/collection_validation_test.cpp | 13 | ||||
-rw-r--r-- | src/mongo/db/catalog/validate_state.h | 8 | ||||
-rw-r--r-- | src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp | 10 |
4 files changed, 42 insertions, 10 deletions
diff --git a/src/mongo/db/catalog/collection_validation.cpp b/src/mongo/db/catalog/collection_validation.cpp index 2f971bb5193..1780df05ee6 100644 --- a/src/mongo/db/catalog/collection_validation.cpp +++ b/src/mongo/db/catalog/collection_validation.cpp @@ -260,19 +260,20 @@ void _reportValidationResults(OperationContext* opCtx, // Report detailed index validation results gathered when using {full: true} for validated // indexes. - for (const auto& index : validateState->getIndexes()) { - const std::string indexName = index->descriptor()->indexName(); - auto& indexResultsMap = results->indexResultsMap; - if (indexResultsMap.find(indexName) == indexResultsMap.end()) { - continue; - } - - auto& vr = indexResultsMap.at(indexName); - + int nIndexes = results->indexResultsMap.size(); + for (const auto& [indexName, vr] : results->indexResultsMap) { if (!vr.valid) { results->valid = false; } + if (validateState->getSkippedIndexes().contains(indexName)) { + // Index internal state was checked and cleared, so it was reported in indexResultsMap, + // but we did not verify the index contents against the collection, so we should exclude + // it from this report. + --nIndexes; + continue; + } + BSONObjBuilder bob(indexDetails.subobjStart(indexName)); bob.appendBool("valid", vr.valid); @@ -291,7 +292,7 @@ void _reportValidationResults(OperationContext* opCtx, results->errors.insert(results->errors.end(), vr.errors.begin(), vr.errors.end()); } - output->append("nIndexes", static_cast<int>(validateState->getIndexes().size())); + output->append("nIndexes", nIndexes); output->append("keysPerIndex", keysPerIndex.done()); output->append("indexDetails", indexDetails.done()); } diff --git a/src/mongo/db/catalog/collection_validation_test.cpp b/src/mongo/db/catalog/collection_validation_test.cpp index c0955df1ed9..22104de0ea4 100644 --- a/src/mongo/db/catalog/collection_validation_test.cpp +++ b/src/mongo/db/catalog/collection_validation_test.cpp @@ -266,6 +266,19 @@ TEST_F(CollectionValidationTest, ValidateEnforceFastCount) { {CollectionValidation::ValidateMode::kForegroundFullEnforceFastCount}); } +TEST_F(BackgroundCollectionValidationTest, ValidateIndexDetailResultsSurfaceVerifyErrors) { + FailPointEnableBlock fp{"WTValidateIndexStructuralDamage"}; + auto opCtx = operationContext(); + insertDataRange(opCtx, 0, 5); // initialize collection + foregroundValidate( + opCtx, + /*valid*/ false, + /*numRecords*/ std::numeric_limits<int32_t>::min(), // uninitialized + /*numInvalidDocuments*/ std::numeric_limits<int32_t>::min(), // uninitialized + /*numErrors*/ 1, + {CollectionValidation::ValidateMode::kForegroundFull}); +} + /** * Waits for a parallel running collection validation operation to start and then hang at a * failpoint. diff --git a/src/mongo/db/catalog/validate_state.h b/src/mongo/db/catalog/validate_state.h index df796c686ce..72f8da3019e 100644 --- a/src/mongo/db/catalog/validate_state.h +++ b/src/mongo/db/catalog/validate_state.h @@ -123,6 +123,10 @@ public: return _indexes; } + const StringSet& getSkippedIndexes() const { + return _skippedIndexes; + } + /** * Map of index names to index cursors. */ @@ -235,6 +239,10 @@ private: std::unique_ptr<SeekableRecordThrottleCursor> _traverseRecordStoreCursor; std::unique_ptr<SeekableRecordThrottleCursor> _seekRecordStoreCursor; + // Stores the set of indexes that will not be validated for some reason, e.g. they are not + // ready. + StringSet _skippedIndexes; + RecordId _firstRecordId; DataThrottle _dataThrottle; diff --git a/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp b/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp index dceca914609..ad83073ba04 100644 --- a/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp +++ b/src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp @@ -83,6 +83,7 @@ namespace { MONGO_FAIL_POINT_DEFINE(WTCompactIndexEBUSY); MONGO_FAIL_POINT_DEFINE(WTEmulateOutOfOrderNextIndexKey); MONGO_FAIL_POINT_DEFINE(WTIndexPauseAfterSearchNear); +MONGO_FAIL_POINT_DEFINE(WTValidateIndexStructuralDamage); using std::string; using std::vector; @@ -311,6 +312,15 @@ void WiredTigerIndex::fullValidate(OperationContext* opCtx, IndexValidateResults* fullResults) const { dassert(opCtx->lockState()->isReadLocked()); if (fullResults && !WiredTigerRecoveryUnit::get(opCtx)->getSessionCache()->isEphemeral()) { + if (WTValidateIndexStructuralDamage.shouldFail()) { + std::string msg = str::stream() << "verify() returned an error. " + << "This indicates structural damage. " + << "Not examining individual index entries."; + fullResults->errors.push_back(msg); + fullResults->valid = false; + return; + } + int err = WiredTigerUtil::verifyTable(opCtx, _uri, &(fullResults->errors)); if (err == EBUSY) { std::string msg = str::stream() |