summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierlauro Sciarelli <pierlauro.sciarelli@mongodb.com>2022-04-04 14:05:12 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-04-04 14:47:00 +0000
commit02393f1c3f5be3465919597c890b3249ea2cc18e (patch)
tree0c10f5debf801193d40bf94e06962bfacad116bb
parent381e4ecfa942fdc06a50875505c1e900bae75653 (diff)
downloadmongo-02393f1c3f5be3465919597c890b3249ea2cc18e.tar.gz
SERVER-65112 TTL index deletions must not target orphaned documents
-rw-r--r--jstests/sharding/ttl_deletes_not_targeting_orphaned_documents.js54
-rw-r--r--src/mongo/db/ttl.cpp3
2 files changed, 57 insertions, 0 deletions
diff --git a/jstests/sharding/ttl_deletes_not_targeting_orphaned_documents.js b/jstests/sharding/ttl_deletes_not_targeting_orphaned_documents.js
new file mode 100644
index 00000000000..9fb36baeecc
--- /dev/null
+++ b/jstests/sharding/ttl_deletes_not_targeting_orphaned_documents.js
@@ -0,0 +1,54 @@
+/**
+ * Test that deletes triggered by TTL index do not affect orphaned documents
+ *
+ * @tags: [requires_fcv_60]
+ */
+(function() {
+"use strict";
+// The range deleter is disabled for this test, hence orphans are not cleared up
+TestData.skipCheckOrphans = true;
+
+const st = new ShardingTest({
+ shards: 2,
+ rs: {
+ nodes: 1,
+ // Reduce TTL Monitor sleep and disable the range deleter
+ setParameter: {ttlMonitorSleepSecs: 1, disableResumableRangeDeleter: true}
+ }
+});
+const dbName = 'test';
+const testDB = st.s.getDB('test');
+const coll = testDB[jsTest.name()];
+const collName = coll.getFullName();
+
+assert.commandWorked(
+ st.s.adminCommand({enableSharding: dbName, primaryShard: st.shard0.shardName}));
+assert.commandWorked(st.s.adminCommand({shardCollection: collName, key: {_id: 1}}));
+
+// Initialize TTL index: delete documents with field `a: <current date>` after 10 seconds
+assert.commandWorked(coll.createIndex({a: 1}, {expireAfterSeconds: 10}));
+
+// Insert documents that are going to be deleted in 10 seconds
+const currTime = new Date();
+var bulk = coll.initializeUnorderedBulkOp();
+const nDocs = 100;
+for (let i = 0; i < nDocs; i++) {
+ bulk.insert({_id: i, a: currTime});
+}
+assert.commandWorked(bulk.execute());
+
+// Move all documents on other shards
+assert.commandWorked(
+ st.s.adminCommand({moveChunk: collName, find: {_id: 0}, to: st.shard1.shardName}));
+
+// Optimistically wait 15 seconds (10 seconds TTL index delay followed by 5 rounds of TTL monitor)
+sleep(15000);
+
+// Verify that TTL index worked properly on owned documents
+assert.eq(coll.countDocuments({}), 0);
+
+// Verify that TTL index did not delete orphaned documents
+assert.eq(nDocs, st.rs0.getPrimary().getCollection(collName).countDocuments({}));
+
+st.stop();
+})();
diff --git a/src/mongo/db/ttl.cpp b/src/mongo/db/ttl.cpp
index 29510d67253..f6d8a984d05 100644
--- a/src/mongo/db/ttl.cpp
+++ b/src/mongo/db/ttl.cpp
@@ -53,6 +53,7 @@
#include "mongo/db/record_id_helpers.h"
#include "mongo/db/repl/replication_coordinator.h"
#include "mongo/db/repl/tenant_migration_access_blocker_registry.h"
+#include "mongo/db/s/operation_sharding_state.h"
#include "mongo/db/s/shard_filtering_metadata_refresh.h"
#include "mongo/db/service_context.h"
#include "mongo/db/stats/resource_consumption_metrics.h"
@@ -287,6 +288,8 @@ private:
uassertStatusOK(userAllowedWriteNS(opCtx, nss));
+ // Attach IGNORED shard version to skip orphans (the range deleter will clear them up)
+ auto scopedRole = ScopedSetShardRole(opCtx, nss, ChunkVersion::IGNORED(), boost::none);
AutoGetCollection coll(opCtx, nss, MODE_IX);
// The collection with `uuid` might be renamed before the lock and the wrong namespace would
// be locked and looked up so we double check here.