diff options
-rw-r--r-- | jstests/sharding/ttl_deletes_not_targeting_orphaned_documents.js | 54 | ||||
-rw-r--r-- | src/mongo/db/ttl.cpp | 3 |
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. |