diff options
Diffstat (limited to 'src/mongo/db')
-rw-r--r-- | src/mongo/db/commands/set_feature_compatibility_version_command.cpp | 29 | ||||
-rw-r--r-- | src/mongo/db/persistent_task_store.h | 2 | ||||
-rw-r--r-- | src/mongo/db/s/migration_coordinator.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/s/migration_destination_manager.cpp | 9 | ||||
-rw-r--r-- | src/mongo/db/s/migration_util.cpp | 33 | ||||
-rw-r--r-- | src/mongo/db/s/migration_util.h | 2 | ||||
-rw-r--r-- | src/mongo/db/s/migration_util_test.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/s/range_deletion_task.idl | 2 | ||||
-rw-r--r-- | src/mongo/db/s/range_deletion_util.cpp | 19 | ||||
-rw-r--r-- | src/mongo/db/s/range_deletion_util.h | 14 | ||||
-rw-r--r-- | src/mongo/db/stats/storage_stats.cpp | 8 |
11 files changed, 86 insertions, 46 deletions
diff --git a/src/mongo/db/commands/set_feature_compatibility_version_command.cpp b/src/mongo/db/commands/set_feature_compatibility_version_command.cpp index 6699248551a..13c8e238bcc 100644 --- a/src/mongo/db/commands/set_feature_compatibility_version_command.cpp +++ b/src/mongo/db/commands/set_feature_compatibility_version_command.cpp @@ -105,6 +105,7 @@ MONGO_FAIL_POINT_DEFINE(hangWhileUpgrading); MONGO_FAIL_POINT_DEFINE(failDowngrading); MONGO_FAIL_POINT_DEFINE(hangWhileDowngrading); MONGO_FAIL_POINT_DEFINE(hangBeforeUpdatingFcvDoc); +MONGO_FAIL_POINT_DEFINE(hangBeforeDrainingMigrations); /** * Ensures that only one instance of setFeatureCompatibilityVersion can run at a given time. @@ -395,7 +396,8 @@ public: invariant(serverGlobalParams.clusterRole == ClusterRole::ShardServer); // TODO SERVER-64162 Destroy the BalancerStatsRegistry if (actualVersion > requestedVersion && - !feature_flags::gNoMoreAutoSplitter.isEnabledOnVersion(requestedVersion)) { + !feature_flags::gOrphanTracking.isEnabledOnVersion(requestedVersion)) { + ScopedRangeDeleterLock rangeDeleterLock(opCtx); clearOrphanCountersFromRangeDeletionTasks(opCtx); } @@ -436,12 +438,17 @@ public: _runDowngrade(opCtx, request, changeTimestamp); } + hangBeforeDrainingMigrations.pauseWhileSet(); { boost::optional<MigrationBlockingGuard> drainOldMoveChunks; + bool orphanTrackingCondition = + serverGlobalParams.clusterRole == ClusterRole::ShardServer && + !feature_flags::gOrphanTracking.isEnabledOnVersion(actualVersion) && + feature_flags::gOrphanTracking.isEnabledOnVersion(requestedVersion); // Drain moveChunks if the actualVersion relies on the old migration protocol but the - // requestedVersion uses the new one (upgrading) or we're persisting the new chunk - // version format. + // requestedVersion uses the new one (upgrading), we're persisting the new chunk + // version format, or we are adding the numOrphans field to range deletion documents. if ((!feature_flags::gFeatureFlagMigrationRecipientCriticalSection.isEnabledOnVersion( actualVersion) && feature_flags::gFeatureFlagMigrationRecipientCriticalSection.isEnabledOnVersion( @@ -449,13 +456,20 @@ public: (!feature_flags::gFeatureFlagNewPersistedChunkVersionFormat.isEnabledOnVersion( actualVersion) && feature_flags::gFeatureFlagNewPersistedChunkVersionFormat.isEnabledOnVersion( - requestedVersion))) { + requestedVersion)) || + orphanTrackingCondition) { drainOldMoveChunks.emplace(opCtx, "setFeatureCompatibilityVersionUpgrade"); // At this point, because we are holding the MigrationBlockingGuard, no new // migrations can start and there are no active ongoing ones. Still, there could // be migrations pending recovery. Drain them. migrationutil::drainMigrationsPendingRecovery(opCtx); + + if (orphanTrackingCondition) { + // TODO SERVER-64162 Initialize the BalancerStatsRegistry + ScopedRangeDeleterLock rangeDeleterLock(opCtx); + setOrphanCountersOnRangeDeletionTasks(opCtx); + } } // Complete transition by updating the local FCV document to the fully upgraded or @@ -569,13 +583,6 @@ private: abortAllReshardCollection(opCtx); } - if (serverGlobalParams.clusterRole == ClusterRole::ShardServer && - request.getPhase() == SetFCVPhaseEnum::kComplete && - feature_flags::gNoMoreAutoSplitter.isEnabledOnVersion(requestedVersion)) { - // TODO SERVER-64162 Initialize the BalancerStatsRegistry - setOrphanCountersOnRangeDeletionTasks(opCtx); - } - // Create the pre-images collection if the feature flag is enabled on the requested version. // TODO SERVER-61770: Remove once FCV 6.0 becomes last-lts. if (feature_flags::gFeatureFlagChangeStreamPreAndPostImages.isEnabledOnVersion( diff --git a/src/mongo/db/persistent_task_store.h b/src/mongo/db/persistent_task_store.h index 8e59d6ed280..d5ef0e50d49 100644 --- a/src/mongo/db/persistent_task_store.h +++ b/src/mongo/db/persistent_task_store.h @@ -54,6 +54,8 @@ const WriteConcernOptions kMajorityWriteConcernNoTimeout{WriteConcernOptions::kM WriteConcernOptions::SyncMode::UNSET, WriteConcernOptions::kNoTimeout}; +const WriteConcernOptions kLocalWriteConcern; + } // namespace WriteConcerns template <typename T> diff --git a/src/mongo/db/s/migration_coordinator.cpp b/src/mongo/db/s/migration_coordinator.cpp index 5096442f56e..fe96ea1accb 100644 --- a/src/mongo/db/s/migration_coordinator.cpp +++ b/src/mongo/db/s/migration_coordinator.cpp @@ -40,6 +40,7 @@ #include "mongo/logv2/log.h" #include "mongo/platform/atomic_word.h" #include "mongo/s/pm2423_feature_flags_gen.h" +#include "mongo/s/sharding_feature_flags_gen.h" #include "mongo/util/fail_point.h" namespace mongo { @@ -125,6 +126,9 @@ void MigrationCoordinator::startMigration(OperationContext* opCtx) { donorDeletionTask.setPending(true); const auto currentTime = VectorClock::get(opCtx)->getTime(); donorDeletionTask.setTimestamp(currentTime.clusterTime().asTimestamp()); + if (feature_flags::gOrphanTracking.isEnabled(serverGlobalParams.featureCompatibility)) { + donorDeletionTask.setNumOrphanDocs(0); + } migrationutil::persistRangeDeletionTaskLocally( opCtx, donorDeletionTask, WriteConcerns::kMajorityWriteConcernShardingTimeout); } @@ -239,8 +243,7 @@ SemiFuture<void> MigrationCoordinator::_commitMigrationOnDonorAndRecipient( auto numOrphans = migrationutil::retrieveNumOrphansFromRecipient(opCtx, _migrationInfo); if (numOrphans > 0) { - migrationutil::persistUpdatedNumOrphans( - opCtx, BSON("_id" << _migrationInfo.getId()), numOrphans); + migrationutil::persistUpdatedNumOrphans(opCtx, _migrationInfo.getId(), numOrphans); } LOGV2_DEBUG(23896, diff --git a/src/mongo/db/s/migration_destination_manager.cpp b/src/mongo/db/s/migration_destination_manager.cpp index 3873ba6d021..71ecf8a67ec 100644 --- a/src/mongo/db/s/migration_destination_manager.cpp +++ b/src/mongo/db/s/migration_destination_manager.cpp @@ -80,6 +80,7 @@ #include "mongo/s/grid.h" #include "mongo/s/pm2423_feature_flags_gen.h" #include "mongo/s/shard_key_pattern.h" +#include "mongo/s/sharding_feature_flags_gen.h" #include "mongo/stdx/chrono.h" #include "mongo/util/fail_point.h" #include "mongo/util/producer_consumer_queue.h" @@ -1233,6 +1234,9 @@ void MigrationDestinationManager::_migrateDriver(OperationContext* outerOpCtx, recipientDeletionTask.setPending(true); const auto currentTime = VectorClock::get(outerOpCtx)->getTime(); recipientDeletionTask.setTimestamp(currentTime.clusterTime().asTimestamp()); + if (feature_flags::gOrphanTracking.isEnabled(serverGlobalParams.featureCompatibility)) { + recipientDeletionTask.setNumOrphanDocs(0); + } // It is illegal to wait for write concern with a session checked out, so persist the // range deletion task with an immediately satsifiable write concern and then wait for @@ -1323,7 +1327,7 @@ void MigrationDestinationManager::_migrateDriver(OperationContext* outerOpCtx, } migrationutil::persistUpdatedNumOrphans( - opCtx, BSON("_id" << _migrationId.get()), batchNumCloned); + opCtx, _migrationId.get(), batchNumCloned); { stdx::lock_guard<Latch> statsLock(_mutex); @@ -1748,8 +1752,7 @@ bool MigrationDestinationManager::_applyMigrateOp(OperationContext* opCtx, const } if (changeInOrphans != 0) { - migrationutil::persistUpdatedNumOrphans( - opCtx, BSON("_id" << _migrationId.get()), changeInOrphans); + migrationutil::persistUpdatedNumOrphans(opCtx, _migrationId.get(), changeInOrphans); } return didAnything; } diff --git a/src/mongo/db/s/migration_util.cpp b/src/mongo/db/s/migration_util.cpp index 93ed0b5ff67..0ee6e29f272 100644 --- a/src/mongo/db/s/migration_util.cpp +++ b/src/mongo/db/s/migration_util.cpp @@ -56,6 +56,7 @@ #include "mongo/db/s/collection_sharding_runtime.h" #include "mongo/db/s/migration_coordinator.h" #include "mongo/db/s/migration_destination_manager.h" +#include "mongo/db/s/range_deletion_util.h" #include "mongo/db/s/shard_filtering_metadata_refresh.h" #include "mongo/db/s/sharding_runtime_d_params_gen.h" #include "mongo/db/s/sharding_state.h" @@ -670,18 +671,28 @@ void persistRangeDeletionTaskLocally(OperationContext* opCtx, } void persistUpdatedNumOrphans(OperationContext* opCtx, - const BSONObj& rangeDeletionQuery, + const UUID& migrationId, const int& changeInOrphans) { - PersistentTaskStore<RangeDeletionTask> store(NamespaceString::kRangeDeletionNamespace); - // TODO (SERVER-54284) Remove writeConflictRetry loop - writeConflictRetry( - opCtx, "updateOrphanCount", NamespaceString::kRangeDeletionNamespace.ns(), [&] { - store.update( - opCtx, - rangeDeletionQuery, - BSON("$inc" << BSON(RangeDeletionTask::kNumOrphanDocsFieldName << changeInOrphans)), - WriteConcernOptions()); - }); + // TODO (SERVER-63819) Remove numOrphanDocsFieldName field from the query + // Add $exists to the query to ensure that on upgrade and downgrade, the numOrphanDocs field + // is only updated after the upgrade procedure has populated it with an initial value. + BSONObj query = BSON("_id" << migrationId << RangeDeletionTask::kNumOrphanDocsFieldName + << BSON("$exists" << true)); + try { + PersistentTaskStore<RangeDeletionTask> store(NamespaceString::kRangeDeletionNamespace); + ScopedRangeDeleterLock rangeDeleterLock(opCtx); + // TODO (SERVER-54284) Remove writeConflictRetry loop + writeConflictRetry( + opCtx, "updateOrphanCount", NamespaceString::kRangeDeletionNamespace.ns(), [&] { + store.update(opCtx, + query, + BSON("$inc" << BSON(RangeDeletionTask::kNumOrphanDocsFieldName + << changeInOrphans)), + WriteConcerns::kLocalWriteConcern); + }); + } catch (const ExceptionFor<ErrorCodes::NoMatchingDocument>&) { + // When upgrading or downgrading, there may be no documents with the orphan count field. + } } int retrieveNumOrphansFromRecipient(OperationContext* opCtx, diff --git a/src/mongo/db/s/migration_util.h b/src/mongo/db/s/migration_util.h index b5af6673729..893752a0faf 100644 --- a/src/mongo/db/s/migration_util.h +++ b/src/mongo/db/s/migration_util.h @@ -148,7 +148,7 @@ void persistRangeDeletionTaskLocally(OperationContext* opCtx, * write concern. */ void persistUpdatedNumOrphans(OperationContext* opCtx, - const BSONObj& rangeDeletionQuery, + const UUID& migrationId, const int& changeInOrphans); /** diff --git a/src/mongo/db/s/migration_util_test.cpp b/src/mongo/db/s/migration_util_test.cpp index d5bdccdd87c..355043931e5 100644 --- a/src/mongo/db/s/migration_util_test.cpp +++ b/src/mongo/db/s/migration_util_test.cpp @@ -344,15 +344,14 @@ TEST_F(MigrationUtilsTest, TestUpdateNumberOfOrphans) { const auto uuid = UUID::gen(); PersistentTaskStore<RangeDeletionTask> store(NamespaceString::kRangeDeletionNamespace); auto rangeDeletionDoc = createDeletionTask(opCtx, kTestNss, uuid, 0, 10); + rangeDeletionDoc.setNumOrphanDocs(0); store.add(opCtx, rangeDeletionDoc); - auto rangeDeletionQuery = BSON("_id" << rangeDeletionDoc.getId()); - - migrationutil::persistUpdatedNumOrphans(opCtx, rangeDeletionQuery, 5); + migrationutil::persistUpdatedNumOrphans(opCtx, rangeDeletionDoc.getId(), 5); rangeDeletionDoc.setNumOrphanDocs(5); ASSERT_EQ(store.count(opCtx, rangeDeletionDoc.toBSON().removeField("timestamp")), 1); - migrationutil::persistUpdatedNumOrphans(opCtx, rangeDeletionQuery, -5); + migrationutil::persistUpdatedNumOrphans(opCtx, rangeDeletionDoc.getId(), -5); rangeDeletionDoc.setNumOrphanDocs(0); ASSERT_EQ(store.count(opCtx, rangeDeletionDoc.toBSON().removeField("timestamp")), 1); } diff --git a/src/mongo/db/s/range_deletion_task.idl b/src/mongo/db/s/range_deletion_task.idl index 611e2170cb6..af7bf53322e 100644 --- a/src/mongo/db/s/range_deletion_task.idl +++ b/src/mongo/db/s/range_deletion_task.idl @@ -80,5 +80,5 @@ structs: optional: true numOrphanDocs: type: safeInt64 - default: 0 description: "The estimated number of orphaned documents in the range" + optional: true diff --git a/src/mongo/db/s/range_deletion_util.cpp b/src/mongo/db/s/range_deletion_util.cpp index f16a117d7ae..5beae5cc6b6 100644 --- a/src/mongo/db/s/range_deletion_util.cpp +++ b/src/mongo/db/s/range_deletion_util.cpp @@ -325,8 +325,7 @@ ExecutorFuture<void> deleteRangeInBatches(const std::shared_ptr<executor::TaskEx keyPattern, range, numDocsToRemovePerBatch)); - migrationutil::persistUpdatedNumOrphans( - opCtx, BSON("_id" << migrationId), -numDeleted); + migrationutil::persistUpdatedNumOrphans(opCtx, migrationId, -numDeleted); if (MONGO_unlikely(hangAfterDoingDeletion.shouldFail())) { hangAfterDoingDeletion.pauseWhileSet(opCtx); @@ -674,14 +673,6 @@ void setOrphanCountersOnRangeDeletionTasks(OperationContext* opCtx) { setNumOrphansOnTask(deletionTask, numOrphansInRange); return true; }); - - auto replClientInfo = repl::ReplClientInfo::forClient(opCtx->getClient()); - replClientInfo.setLastOpToSystemLastOpTime(opCtx); - WriteConcernResult ignoreResult; - uassertStatusOK(waitForWriteConcern(opCtx, - replClientInfo.getLastOp(), - WriteConcerns::kMajorityWriteConcernNoTimeout, - &ignoreResult)); } void clearOrphanCountersFromRangeDeletionTasks(OperationContext* opCtx) { @@ -695,11 +686,17 @@ void clearOrphanCountersFromRangeDeletionTasks(OperationContext* opCtx) { opCtx, allDocsQuery, BSON("$unset" << BSON(RangeDeletionTask::kNumOrphanDocsFieldName << "")), - WriteConcerns::kMajorityWriteConcernNoTimeout); + WriteConcerns::kLocalWriteConcern); }); } catch (const ExceptionFor<ErrorCodes::NoMatchingDocument>&) { // There may be no range deletion tasks, so it is possible no document is updated } } +// TODO (SERVER-65015) Use granular locks for synchronizing orphan tracking +ScopedRangeDeleterLock::ScopedRangeDeleterLock(OperationContext* opCtx) + : _configLock(Lock::DBLock(opCtx, NamespaceString::kConfigDb, MODE_IX)), + _rangeDeletionLock( + Lock::CollectionLock(opCtx, NamespaceString::kRangeDeletionNamespace, MODE_X)) {} + } // namespace mongo diff --git a/src/mongo/db/s/range_deletion_util.h b/src/mongo/db/s/range_deletion_util.h index 614331a500b..5d345f8826e 100644 --- a/src/mongo/db/s/range_deletion_util.h +++ b/src/mongo/db/s/range_deletion_util.h @@ -32,6 +32,7 @@ #include <boost/optional.hpp> +#include "mongo/db/concurrency/d_concurrency.h" #include "mongo/db/namespace_string.h" #include "mongo/db/s/range_deletion_task_gen.h" #include "mongo/executor/task_executor.h" @@ -52,6 +53,19 @@ extern AtomicWord<int> rangeDeleterBatchSize; extern AtomicWord<int> rangeDeleterBatchDelayMS; /** + * Acquires the config db lock in IX mode and the collection lock for config.rangeDeletions in X + * mode. + */ +class ScopedRangeDeleterLock { +public: + ScopedRangeDeleterLock(OperationContext* opCtx); + +private: + Lock::DBLock _configLock; + Lock::CollectionLock _rangeDeletionLock; +}; + +/** * 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. diff --git a/src/mongo/db/stats/storage_stats.cpp b/src/mongo/db/stats/storage_stats.cpp index 3acf204b1a8..00966458fa1 100644 --- a/src/mongo/db/stats/storage_stats.cpp +++ b/src/mongo/db/stats/storage_stats.cpp @@ -43,6 +43,7 @@ #include "mongo/db/timeseries/bucket_catalog.h" #include "mongo/db/timeseries/timeseries_stats.h" #include "mongo/logv2/log.h" +#include "mongo/s/sharding_feature_flags_gen.h" #include "mongo/db/stats/storage_stats.h" @@ -142,8 +143,11 @@ Status appendCollectionStorageStats(OperationContext* opCtx, } } - result->appendNumber(kOrphanCountField, - countOrphanDocsForCollection(opCtx, collection->uuid())); + if (serverGlobalParams.featureCompatibility.isVersionInitialized() && + feature_flags::gOrphanTracking.isEnabled(serverGlobalParams.featureCompatibility)) { + result->appendNumber(kOrphanCountField, + countOrphanDocsForCollection(opCtx, collection->uuid())); + } const RecordStore* recordStore = collection->getRecordStore(); auto storageSize = |