diff options
author | Gregory Wlodarek <gregory.wlodarek@mongodb.com> | 2020-05-05 13:42:17 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-05-05 21:22:38 +0000 |
commit | 1e525750c99b70e21af0b20d4c29159f8329c008 (patch) | |
tree | 782f9ab99642417f9e97f021eb76b48c4649e7ad /src | |
parent | 0684c1761e399146a3a1760162d017d747bc3d3e (diff) | |
download | mongo-1e525750c99b70e21af0b20d4c29159f8329c008.tar.gz |
SERVER-47319 dropIndexes should not invariant if a similar index was created while yielding locks to abort different indexes
(cherry picked from commit 60b2655e069a30dfa1656809b1ae25d77617292c)
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/catalog/drop_indexes.cpp | 52 |
1 files changed, 35 insertions, 17 deletions
diff --git a/src/mongo/db/catalog/drop_indexes.cpp b/src/mongo/db/catalog/drop_indexes.cpp index b862c5549cd..3b947e81851 100644 --- a/src/mongo/db/catalog/drop_indexes.cpp +++ b/src/mongo/db/catalog/drop_indexes.cpp @@ -51,6 +51,8 @@ namespace mongo { namespace { +MONGO_FAIL_POINT_DEFINE(hangAfterAbortingIndexes); + // Field name in dropIndexes command for indexes to drop. constexpr auto kIndexFieldName = "index"_sd; @@ -345,6 +347,11 @@ Status dropIndexes(OperationContext* opCtx, abortedIndexBuilders.insert( abortedIndexBuilders.end(), justAborted.begin(), justAborted.end()); + if (MONGO_unlikely(hangAfterAbortingIndexes.shouldFail())) { + LOGV2(4731900, "Hanging on hangAfterAbortingIndexes fail point"); + hangAfterAbortingIndexes.pauseWhileSet(); + } + // Take an exclusive lock on the collection now to be able to perform index catalog writes // when removing ready indexes from disk. autoColl.emplace(opCtx, dbAndUUID, MODE_X); @@ -379,25 +386,36 @@ Status dropIndexes(OperationContext* opCtx, } } - // If the "*" wildcard was not specified, verify that all the index names belonging to the - // index builder were aborted. + // Drop any ready indexes that were created while we yielded our locks while aborting using + // similar index specs. if (!isWildcard && !abortedIndexBuilders.empty()) { - // This is necessary to check shard version. - OldClientContext ctx(opCtx, collection->ns().ns()); - - // Iterate through all aborted indexes and verify none of them are ready. This would - // indicate a flaw with the abort logic that allows indexes to complete despite the - // dropIndexes command reporting they were aborted. - auto indexCatalog = collection->getIndexCatalog(); - const bool includeUnfinished = false; - const bool noneReady = std::none_of(indexNames.begin(), indexNames.end(), [&](auto name) { - return indexCatalog->findIndexByName(opCtx, name, includeUnfinished); - }); + return writeConflictRetry(opCtx, "dropIndexes", dbAndUUID.toString(), [&] { + WriteUnitOfWork wuow(opCtx); - invariant(noneReady, - str::stream() << "Found completed indexes despite aborting index build: " - << abortedIndexBuilders.front()); - return Status::OK(); + // This is necessary to check shard version. + OldClientContext ctx(opCtx, collection->ns().ns()); + + // Iterate through all the aborted indexes and drop any indexes that are ready in the + // index catalog. This would indicate that while we yielded our locks during the abort + // phase, a new identical index was created. + auto indexCatalog = collection->getIndexCatalog(); + const bool includeUnfinished = false; + for (const auto& indexName : indexNames) { + auto desc = indexCatalog->findIndexByName(opCtx, indexName, includeUnfinished); + if (!desc) { + // A similar index wasn't created while we yielded the locks during abort. + continue; + } + + Status status = dropIndexByDescriptor(opCtx, collection, indexCatalog, desc); + if (!status.isOK()) { + return status; + } + } + + wuow.commit(); + return Status::OK(); + }); } if (!abortedIndexBuilders.empty()) { |