summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Fuschetto <antonio.fuschetto@mongodb.com>2022-04-04 08:51:35 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-04-04 09:32:47 +0000
commit93b609f94dd58452ba28f277a6739b7740b9980a (patch)
tree066f10eb9978a6cb989ba362d72cad55eb484d16
parent09654db603334e7fe422c702f05c7675d00870aa (diff)
downloadmongo-93b609f94dd58452ba28f277a6739b7740b9980a.tar.gz
SERVER-65208 Check the top-chunk before refreshing the local metadata
-rw-r--r--src/mongo/db/s/split_chunk.cpp84
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