diff options
author | Pierlauro Sciarelli <pierlauro.sciarelli@mongodb.com> | 2022-07-11 14:19:10 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-07-11 15:29:05 +0000 |
commit | 623431cfec4198ebac1723e968eeea77170241f1 (patch) | |
tree | a55a8fb647089cb2323b43ad81b9c8c1c1a121f5 /src/mongo/db/s | |
parent | 37f750c8372b7186ae96615a968307936d18e5b2 (diff) | |
download | mongo-623431cfec4198ebac1723e968eeea77170241f1.tar.gz |
SERVER-67779 Refactor `deleteRangeInBatches` to don't require an executor
Diffstat (limited to 'src/mongo/db/s')
-rw-r--r-- | src/mongo/db/s/range_deletion_util.cpp | 205 | ||||
-rw-r--r-- | src/mongo/db/s/range_deletion_util.h | 13 |
2 files changed, 115 insertions, 103 deletions
diff --git a/src/mongo/db/s/range_deletion_util.cpp b/src/mongo/db/s/range_deletion_util.cpp index b4ed292c257..b7dd5efa719 100644 --- a/src/mongo/db/s/range_deletion_util.cpp +++ b/src/mongo/db/s/range_deletion_util.cpp @@ -290,108 +290,21 @@ void markRangeDeletionTaskAsProcessing(OperationContext* opCtx, const UUID& migr * Delete the range in a sequence of batches until there are no more documents to delete or deletion * returns an error. */ -ExecutorFuture<void> deleteRangeInBatches(const std::shared_ptr<executor::TaskExecutor>& executor, - const NamespaceString& nss, - const UUID& collectionUuid, - const BSONObj& keyPattern, - const ChunkRange& range, - const UUID& migrationId) { - return ExecutorFuture<void>(executor) - .then([=] { - bool allDocsRemoved = false; - // Delete all batches in this range unless a stepdown error occurs. Do not yield the - // executor to ensure that this range is fully deleted before another range is - // processed. - while (!allDocsRemoved) { - try { - allDocsRemoved = withTemporaryOperationContext( - [=](OperationContext* opCtx) { - int numDocsToRemovePerBatch = rangeDeleterBatchSize.load(); - if (numDocsToRemovePerBatch <= 0) { - numDocsToRemovePerBatch = kRangeDeleterBatchSizeDefault; - } - - Milliseconds delayBetweenBatches(rangeDeleterBatchDelayMS.load()); - - LOGV2_DEBUG(5346200, - 1, - "Starting batch deletion", - "namespace"_attr = nss, - "range"_attr = redact(range.toString()), - "numDocsToRemovePerBatch"_attr = numDocsToRemovePerBatch, - "delayBetweenBatches"_attr = delayBetweenBatches); - - ensureRangeDeletionTaskStillExists(opCtx, migrationId); - - int numDeleted; - - { - AutoGetCollection collection(opCtx, nss, MODE_IX); - - // Ensure the collection exists and has not been dropped or dropped - // and recreated - uassert( - ErrorCodes:: - RangeDeletionAbandonedBecauseCollectionWithUUIDDoesNotExist, - "Collection has been dropped since enqueuing this range " - "deletion task. No need to delete documents.", - !collectionUuidHasChanged( - nss, collection.getCollection(), collectionUuid)); - - markRangeDeletionTaskAsProcessing(opCtx, migrationId); - - numDeleted = - uassertStatusOK(deleteNextBatch(opCtx, - collection.getCollection(), - keyPattern, - range, - numDocsToRemovePerBatch)); - - migrationutil::persistUpdatedNumOrphans( - opCtx, migrationId, collectionUuid, -numDeleted); - - if (MONGO_unlikely(hangAfterDoingDeletion.shouldFail())) { - hangAfterDoingDeletion.pauseWhileSet(opCtx); - } - } - - LOGV2_DEBUG(23769, - 1, - "Deleted documents in pass", - "numDeleted"_attr = numDeleted, - "namespace"_attr = nss.ns(), - "collectionUUID"_attr = collectionUuid, - "range"_attr = range.toString()); - - if (numDeleted > 0) { - // (SERVER-62368) The range-deleter executor is mono-threaded, so - // sleeping synchronously for `delayBetweenBatches` ensures that no - // other batch is going to be cleared up before the expected delay. - opCtx->sleepFor(delayBetweenBatches); - } - - return numDeleted < numDocsToRemovePerBatch; - }, - nss); - } catch (const DBException& ex) { - // Errors other than those indicating stepdown and those that indicate that the - // range deletion can no longer occur should be retried. - auto errorCode = ex.code(); - if (errorCode == - ErrorCodes:: - RangeDeletionAbandonedBecauseCollectionWithUUIDDoesNotExist || - errorCode == - ErrorCodes::RangeDeletionAbandonedBecauseTaskDocumentDoesNotExist || - errorCode == ErrorCodes::KeyPatternShorterThanBound || - ErrorCodes::isShutdownError(errorCode) || - ErrorCodes::isNotPrimaryError(errorCode)) { - return ex.toStatus(); - }; - } - } - return Status::OK(); - }) - .ignoreValue(); +ExecutorFuture<void> deleteRangeInBatchesWithExecutor( + const std::shared_ptr<executor::TaskExecutor>& executor, + const NamespaceString& nss, + const UUID& collectionUuid, + const BSONObj& keyPattern, + const ChunkRange& range, + const UUID& migrationId) { + return ExecutorFuture<void>(executor).then([=] { + return withTemporaryOperationContext( + [=](OperationContext* opCtx) { + return deleteRangeInBatches( + opCtx, nss, collectionUuid, keyPattern, range, migrationId); + }, + nss); + }); } void removePersistentRangeDeletionTask(const NamespaceString& nss, UUID migrationId) { @@ -447,6 +360,92 @@ std::vector<RangeDeletionTask> getPersistentRangeDeletionTasks(OperationContext* } // namespace +Status deleteRangeInBatches(OperationContext* opCtx, + const NamespaceString& nss, + const UUID& collectionUuid, + const BSONObj& keyPattern, + const ChunkRange& range, + const UUID& migrationId) { + bool allDocsRemoved = false; + // Delete all batches in this range unless a stepdown error occurs. Do not yield the + // executor to ensure that this range is fully deleted before another range is + // processed. + while (!allDocsRemoved) { + try { + int numDocsToRemovePerBatch = rangeDeleterBatchSize.load(); + if (numDocsToRemovePerBatch <= 0) { + numDocsToRemovePerBatch = kRangeDeleterBatchSizeDefault; + } + + Milliseconds delayBetweenBatches(rangeDeleterBatchDelayMS.load()); + + LOGV2_DEBUG(5346200, + 1, + "Starting batch deletion", + "namespace"_attr = nss, + "range"_attr = redact(range.toString()), + "numDocsToRemovePerBatch"_attr = numDocsToRemovePerBatch, + "delayBetweenBatches"_attr = delayBetweenBatches); + + ensureRangeDeletionTaskStillExists(opCtx, migrationId); + + int numDeleted; + { + AutoGetCollection collection(opCtx, nss, MODE_IX); + + // Ensure the collection exists and has not been dropped or dropped + // and recreated + uassert(ErrorCodes::RangeDeletionAbandonedBecauseCollectionWithUUIDDoesNotExist, + "Collection has been dropped since enqueuing this range " + "deletion task. No need to delete documents.", + !collectionUuidHasChanged(nss, collection.getCollection(), collectionUuid)); + + markRangeDeletionTaskAsProcessing(opCtx, migrationId); + + numDeleted = uassertStatusOK(deleteNextBatch( + opCtx, collection.getCollection(), keyPattern, range, numDocsToRemovePerBatch)); + + migrationutil::persistUpdatedNumOrphans( + opCtx, migrationId, collectionUuid, -numDeleted); + + if (MONGO_unlikely(hangAfterDoingDeletion.shouldFail())) { + hangAfterDoingDeletion.pauseWhileSet(opCtx); + } + } + + LOGV2_DEBUG(23769, + 1, + "Deleted documents in pass", + "numDeleted"_attr = numDeleted, + "namespace"_attr = nss.ns(), + "collectionUUID"_attr = collectionUuid, + "range"_attr = range.toString()); + + if (numDeleted > 0) { + // (SERVER-62368) The range-deleter executor is mono-threaded, so + // sleeping synchronously for `delayBetweenBatches` ensures that no + // other batch is going to be cleared up before the expected delay. + opCtx->sleepFor(delayBetweenBatches); + } + + allDocsRemoved = numDeleted < numDocsToRemovePerBatch; + } catch (const DBException& ex) { + // Errors other than those indicating stepdown and those that indicate that the + // range deletion can no longer occur should be retried. + auto errorCode = ex.code(); + if (errorCode == + ErrorCodes::RangeDeletionAbandonedBecauseCollectionWithUUIDDoesNotExist || + errorCode == ErrorCodes::RangeDeletionAbandonedBecauseTaskDocumentDoesNotExist || + errorCode == ErrorCodes::KeyPatternShorterThanBound || + ErrorCodes::isShutdownError(errorCode) || + ErrorCodes::isNotPrimaryError(errorCode)) { + return ex.toStatus(); + }; + } + } + return Status::OK(); +} + void snapshotRangeDeletionsForRename(OperationContext* opCtx, const NamespaceString& fromNss, const NamespaceString& toNss) { @@ -527,7 +526,7 @@ SharedSemiFuture<void> removeDocumentsInRange( "namespace"_attr = nss.ns(), "range"_attr = redact(range.toString())); - return deleteRangeInBatches( + return deleteRangeInBatchesWithExecutor( executor, nss, collectionUuid, keyPattern, range, migrationId) .onCompletion([=](Status s) { if (!s.isOK() && diff --git a/src/mongo/db/s/range_deletion_util.h b/src/mongo/db/s/range_deletion_util.h index aaf6bfae75f..9569f7f5607 100644 --- a/src/mongo/db/s/range_deletion_util.h +++ b/src/mongo/db/s/range_deletion_util.h @@ -40,6 +40,8 @@ namespace mongo { /** + * DO NOT USE - only necessary for the legacy range deleter + * * Deletes a range of orphaned documents for the given namespace and collection UUID. Returns a * future which will be resolved when the range has finished being deleted. The resulting future * will contain an error in cases where the range could not be deleted successfully. @@ -63,6 +65,17 @@ SharedSemiFuture<void> removeDocumentsInRange( Seconds delayForActiveQueriesOnSecondariesToComplete); /** + * Delete the range in a sequence of batches until there are no more documents to delete or deletion + * returns an error. + */ +Status deleteRangeInBatches(OperationContext* opCtx, + const NamespaceString& nss, + const UUID& collectionUuid, + const BSONObj& keyPattern, + const ChunkRange& range, + const UUID& migrationId); + +/** * - Retrieves source collection's persistent range deletion tasks from `config.rangeDeletions` * - Associates tasks to the target collection * - Stores tasks in `config.rangeDeletionsForRename` |