Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-34904

recipient shard may be unable to accept versioned requests if it doesn't receive setShardVersion for drop and collection is recreated

    • Sharding EMEA
    • ALL
    • Hide

      Apply this diff and run jstests/sharding/upsert_sharded.js. The diff removes the setShardVersion from dropCollection, but ensures just the primary shard refreshes after the drop in the test.

      diff --git a/jstests/sharding/upsert_sharded.js b/jstests/sharding/upsert_sharded.js
      index 5d3dde7..b279b02 100644
      --- a/jstests/sharding/upsert_sharded.js
      +++ b/jstests/sharding/upsert_sharded.js
      @@ -68,6 +68,7 @@
           assert.writeError(upsertedResult({"x.x": {$eq: 1}}, {$set: {a: 1}}));     coll.drop();
      +    assert.commandWorked(st.shard0.adminCommand({_flushRoutingTableCacheUpdates: coll + ""}));     st.ensurePrimaryShard(coll.getDB() + "", st.shard0.shardName);
           assert.commandWorked(admin.runCommand({shardCollection: coll + "", key: {'x.x': 1}}));
      diff --git a/src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp b/src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp
      index 59d2511..b3191d1 100644
      --- a/src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp
      +++ b/src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp
      @@ -429,57 +429,6 @@ Status ShardingCatalogManager::dropCollection(OperationContext* opCtx, const Nam     LOG(1) << "dropCollection " << nss.ns() << " collection marked as dropped";-    for (const auto& shardEntry : allShards) {
      -        auto swShard = shardRegistry->getShard(opCtx, shardEntry.getName());
      -        if (!swShard.isOK()) {
      -            return swShard.getStatus();
      -        }
      -
      -        const auto& shard = swShard.getValue();
      -
      -        SetShardVersionRequest ssv = SetShardVersionRequest::makeForVersioningNoPersist(
      -            shardRegistry->getConfigServerConnectionString(),
      -            shardEntry.getName(),
      -            fassert(28781, ConnectionString::parse(shardEntry.getHost())),
      -            nss,
      -            ChunkVersion::DROPPED(),
      -            true);
      -
      -        auto ssvResult = shard->runCommandWithFixedRetryAttempts(
      -            opCtx,
      -            ReadPreferenceSetting{ReadPreference::PrimaryOnly},
      -            "admin",
      -            ssv.toBSON(),
      -            Shard::RetryPolicy::kIdempotent);
      -
      -        if (!ssvResult.isOK()) {
      -            return ssvResult.getStatus();
      -        }
      -
      -        auto ssvStatus = std::move(ssvResult.getValue().commandStatus);
      -        if (!ssvStatus.isOK()) {
      -            return ssvStatus;
      -        }
      -
      -        auto unsetShardingStatus = shard->runCommandWithFixedRetryAttempts(
      -            opCtx,
      -            ReadPreferenceSetting{ReadPreference::PrimaryOnly},
      -            "admin",
      -            BSON("unsetSharding" << 1),
      -            Shard::RetryPolicy::kIdempotent);
      -
      -        if (!unsetShardingStatus.isOK()) {
      -            return unsetShardingStatus.getStatus();
      -        }
      -
      -        auto unsetShardingResult = std::move(unsetShardingStatus.getValue().commandStatus);
      -        if (!unsetShardingResult.isOK()) {
      -            return unsetShardingResult;
      -        }
      -    }
      -
      -    LOG(1) << "dropCollection " << nss.ns() << " completed";
      -
           catalogClient
               ->logChange(opCtx,
                           "dropCollection", 
      Show
      Apply this diff and run jstests/sharding/upsert_sharded.js. The diff removes the setShardVersion from dropCollection, but ensures just the primary shard refreshes after the drop in the test. diff --git a/jstests/sharding/upsert_sharded.js b/jstests/sharding/upsert_sharded.js index 5d3dde7..b279b02 100644 --- a/jstests/sharding/upsert_sharded.js +++ b/jstests/sharding/upsert_sharded.js @@ -68,6 +68,7 @@ assert.writeError(upsertedResult({"x.x": {$eq: 1}}, {$set: {a: 1}})); coll.drop(); + assert.commandWorked(st.shard0.adminCommand({_flushRoutingTableCacheUpdates: coll + ""})); st.ensurePrimaryShard(coll.getDB() + "", st.shard0.shardName); assert.commandWorked(admin.runCommand({shardCollection: coll + "", key: {'x.x': 1}})); diff --git a/src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp b/src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp index 59d2511..b3191d1 100644 --- a/src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp +++ b/src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp @@ -429,57 +429,6 @@ Status ShardingCatalogManager::dropCollection(OperationContext* opCtx, const Nam LOG(1) << "dropCollection " << nss.ns() << " collection marked as dropped";- for (const auto& shardEntry : allShards) { - auto swShard = shardRegistry->getShard(opCtx, shardEntry.getName()); - if (!swShard.isOK()) { - return swShard.getStatus(); - } - - const auto& shard = swShard.getValue(); - - SetShardVersionRequest ssv = SetShardVersionRequest::makeForVersioningNoPersist( - shardRegistry->getConfigServerConnectionString(), - shardEntry.getName(), - fassert(28781, ConnectionString::parse(shardEntry.getHost())), - nss, - ChunkVersion::DROPPED(), - true); - - auto ssvResult = shard->runCommandWithFixedRetryAttempts( - opCtx, - ReadPreferenceSetting{ReadPreference::PrimaryOnly}, - "admin", - ssv.toBSON(), - Shard::RetryPolicy::kIdempotent); - - if (!ssvResult.isOK()) { - return ssvResult.getStatus(); - } - - auto ssvStatus = std::move(ssvResult.getValue().commandStatus); - if (!ssvStatus.isOK()) { - return ssvStatus; - } - - auto unsetShardingStatus = shard->runCommandWithFixedRetryAttempts( - opCtx, - ReadPreferenceSetting{ReadPreference::PrimaryOnly}, - "admin", - BSON("unsetSharding" << 1), - Shard::RetryPolicy::kIdempotent); - - if (!unsetShardingStatus.isOK()) { - return unsetShardingStatus.getStatus(); - } - - auto unsetShardingResult = std::move(unsetShardingStatus.getValue().commandStatus); - if (!unsetShardingResult.isOK()) { - return unsetShardingResult; - } - } - - LOG(1) << "dropCollection " << nss.ns() << " completed"; - catalogClient ->logChange(opCtx, "dropCollection",
    • 41

      Let's say a (non-primary shard) recipient shard does not receive setShardVersion on dropCollection and it had cached chunks for the old collection in its config.cache.chunks.<ns>.

      The first time it will refresh after the drop and recreate is when a chunk is being migrated to it (because recipient shards refresh at the beginning of _recvChunkStart).

      On this refresh, it will see an epoch mismatch and query config.chunks with $gte 0|0. If this is the first chunk to be migrated in the new collection, the version of the chunk with the highest version in config.chunks will be 1|x. The recipient shard will persist this new chunk, but may not delete the "overlapping" (garbage) chunks from the previous collection if the shard key is different (see SERVER-34856).

      The next time the recipient will refresh will be on a versioned request. Since its config.cache.chunks.<ns> contains garbage chunks, the one with the highest version will be used for querying config.chuns.

      Since the control chunk is the one whose minor version is set to 1 (the migrated chunk's minor version is set to 0), the recipient shard may see only chunks that don't belong to it.

      So, in all shardVersion checks, the recipient shard' its CSS will report that it does not own any chunks for the collection.

      So, no versioned requests from a fresh mongos will succeed against the recipient shard.

            Assignee:
            backlog-server-sharding-emea [DO NOT USE] Backlog - Sharding EMEA
            Reporter:
            esha.maharishi@mongodb.com Esha Maharishi (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: