diff options
author | Antonio Fuschetto <antonio.fuschetto@mongodb.com> | 2022-04-04 08:51:35 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-04-04 09:32:47 +0000 |
commit | 93b609f94dd58452ba28f277a6739b7740b9980a (patch) | |
tree | 066f10eb9978a6cb989ba362d72cad55eb484d16 /src/mongo/db | |
parent | 09654db603334e7fe422c702f05c7675d00870aa (diff) | |
download | mongo-93b609f94dd58452ba28f277a6739b7740b9980a.tar.gz |
SERVER-65208 Check the top-chunk before refreshing the local metadata
Diffstat (limited to 'src/mongo/db')
-rw-r--r-- | src/mongo/db/s/split_chunk.cpp | 84 |
1 files changed, 44 insertions, 40 deletions
diff --git a/src/mongo/db/s/split_chunk.cpp b/src/mongo/db/s/split_chunk.cpp index cd3f7d15322..a97efd9be55 100644 --- a/src/mongo/db/s/split_chunk.cpp +++ b/src/mongo/db/s/split_chunk.cpp @@ -163,6 +163,49 @@ StatusWith<boost::optional<ChunkRange>> splitChunk(OperationContext* opCtx, std::move(splitPoints), fromChunkSplitter); + // Get the chunk containing a single document (if any) to perform the top-chunk optimization. + auto topChunkRange = [&] { + AutoGetCollection collection(opCtx, nss, MODE_IS); + if (!collection) { + LOGV2_WARNING(23778, + "will not perform top-chunk checking since {namespace} does not " + "exist after splitting", + logAttrs(nss)); + return boost::optional<ChunkRange>(boost::none); + } + + // Allow multiKey based on the invariant that shard keys must be single-valued. + // Therefore, any multi-key index prefixed by shard key cannot be multikey over the + // shard key fields. + auto shardKeyIdx = findShardKeyPrefixedIndex(opCtx, + *collection, + collection->getIndexCatalog(), + keyPatternObj, + false /* requireSingleKey */); + if (!shardKeyIdx) { + return boost::optional<ChunkRange>(boost::none); + } + + auto backChunk = ChunkType(); + backChunk.setMin(request.getSplitPoints().back()); + backChunk.setMax(chunkRange.getMax()); + + auto frontChunk = ChunkType(); + frontChunk.setMin(chunkRange.getMin()); + frontChunk.setMax(request.getSplitPoints().front()); + + KeyPattern shardKeyPattern(keyPatternObj); + if (shardKeyPattern.globalMax().woCompare(backChunk.getMax()) == 0 && + checkIfSingleDoc(opCtx, collection.getCollection(), *shardKeyIdx, &backChunk)) { + return boost::optional<ChunkRange>(ChunkRange(backChunk.getMin(), backChunk.getMax())); + } else if (shardKeyPattern.globalMin().woCompare(frontChunk.getMin()) == 0 && + checkIfSingleDoc(opCtx, collection.getCollection(), *shardKeyIdx, &frontChunk)) { + return boost::optional<ChunkRange>( + ChunkRange(frontChunk.getMin(), frontChunk.getMax())); + } + return boost::optional<ChunkRange>(boost::none); + }(); + auto configCmdObj = request.toConfigCommandBSON(ShardingCatalogClient::kMajorityWriteConcern.toBSON()); @@ -202,14 +245,11 @@ StatusWith<boost::optional<ChunkRange>> splitChunk(OperationContext* opCtx, return commandStatus; } - // // If _configsvrCommitChunkSplit returned an error, look at the metadata to // determine if the split actually did happen. This can happen if there's a network error // getting the response from the first call to _configsvrCommitChunkSplit, but it actually // succeeds, thus the automatic retry fails with a precondition violation, for example. - // if (!commandStatus.isOK() || !writeConcernStatus.isOK()) { - if (checkMetadataForSuccessfulSplitChunk( opCtx, nss, expectedCollectionEpoch, chunkRange, request.getSplitPoints())) { // Split was committed. @@ -220,43 +260,7 @@ StatusWith<boost::optional<ChunkRange>> splitChunk(OperationContext* opCtx, } } - AutoGetCollection collection(opCtx, nss, MODE_IS); - if (!collection) { - LOGV2_WARNING( - 23778, - "will not perform top-chunk checking since {namespace} does not exist after splitting", - logAttrs(nss)); - return boost::optional<ChunkRange>(boost::none); - } - - // Allow multiKey based on the invariant that shard keys must be single-valued. Therefore, - // any multi-key index prefixed by shard key cannot be multikey over the shard key fields. - auto shardKeyIdx = findShardKeyPrefixedIndex(opCtx, - *collection, - collection->getIndexCatalog(), - keyPatternObj, - /*requireSingleKey=*/false); - if (!shardKeyIdx) { - return boost::optional<ChunkRange>(boost::none); - } - - auto backChunk = ChunkType(); - backChunk.setMin(request.getSplitPoints().back()); - backChunk.setMax(chunkRange.getMax()); - - auto frontChunk = ChunkType(); - frontChunk.setMin(chunkRange.getMin()); - frontChunk.setMax(request.getSplitPoints().front()); - - KeyPattern shardKeyPattern(keyPatternObj); - if (shardKeyPattern.globalMax().woCompare(backChunk.getMax()) == 0 && - checkIfSingleDoc(opCtx, collection.getCollection(), *shardKeyIdx, &backChunk)) { - return boost::optional<ChunkRange>(ChunkRange(backChunk.getMin(), backChunk.getMax())); - } else if (shardKeyPattern.globalMin().woCompare(frontChunk.getMin()) == 0 && - checkIfSingleDoc(opCtx, collection.getCollection(), *shardKeyIdx, &frontChunk)) { - return boost::optional<ChunkRange>(ChunkRange(frontChunk.getMin(), frontChunk.getMax())); - } - return boost::optional<ChunkRange>(boost::none); + return topChunkRange; } } // namespace mongo |