summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/commands/set_feature_compatibility_version_command.cpp29
-rw-r--r--src/mongo/db/persistent_task_store.h2
-rw-r--r--src/mongo/db/s/migration_coordinator.cpp7
-rw-r--r--src/mongo/db/s/migration_destination_manager.cpp9
-rw-r--r--src/mongo/db/s/migration_util.cpp33
-rw-r--r--src/mongo/db/s/migration_util.h2
-rw-r--r--src/mongo/db/s/migration_util_test.cpp7
-rw-r--r--src/mongo/db/s/range_deletion_task.idl2
-rw-r--r--src/mongo/db/s/range_deletion_util.cpp19
-rw-r--r--src/mongo/db/s/range_deletion_util.h14
-rw-r--r--src/mongo/db/stats/storage_stats.cpp8
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 =