Skip to content

Commit 342b9c5

Browse files
PolPinolEvergreen Agent
authored and
Evergreen Agent
committed
SERVER-74084 Implement zones checks in checkConsistencyMetadata command
1 parent 79b5f30 commit 342b9c5

6 files changed

+193
-31
lines changed

jstests/sharding/check_metadata_consistency.js

+43
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,49 @@ function getNewDb() {
241241
assert.eq(0, inconsistencies.length, tojson(inconsistencies));
242242
})();
243243

244+
(function testRoutingTableInconsistency() {
245+
const db = getNewDb();
246+
const kSourceCollName = "coll";
247+
const ns = db[kSourceCollName].getFullName();
248+
249+
st.shardColl(db[kSourceCollName], {skey: 1});
250+
251+
// Insert a RoutingTableRangeOverlap inconsistency
252+
const collUuid = st.config.collections.findOne({_id: ns}).uuid;
253+
assert.commandWorked(st.config.chunks.updateOne({uuid: collUuid}, {$set: {max: {skey: 10}}}));
254+
255+
// Insert a ZonesRangeOverlap inconsistency
256+
let entry = {
257+
_id: {ns: ns, min: {"skey": -100}},
258+
ns: ns,
259+
min: {"skey": -100},
260+
max: {"skey": 100},
261+
tag: "a",
262+
};
263+
assert.commandWorked(st.config.tags.insert(entry));
264+
entry = {
265+
_id: {ns: ns, min: {"skey": 50}},
266+
ns: ns,
267+
min: {"skey": 50},
268+
max: {"skey": 150},
269+
tag: "a",
270+
};
271+
assert.commandWorked(st.config.tags.insert(entry));
272+
273+
// Database level mode command
274+
let inconsistencies = db.checkMetadataConsistency().toArray();
275+
assert.eq(2, inconsistencies.length, tojson(inconsistencies));
276+
assert(inconsistencies.some(object => object.type === "RoutingTableRangeOverlap"),
277+
tojson(inconsistencies));
278+
assert(inconsistencies.some(object => object.type === "ZonesRangeOverlap"),
279+
tojson(inconsistencies));
280+
281+
// Clean up the database to pass the hooks that detect inconsistencies
282+
db.dropDatabase();
283+
inconsistencies = mongos.getDB("admin").checkMetadataConsistency().toArray();
284+
assert.eq(0, inconsistencies.length, tojson(inconsistencies));
285+
})();
286+
244287
(function testClusterLevelMode() {
245288
const db_MisplacedCollection1 = getNewDb();
246289
const db_MisplacedCollection2 = getNewDb();

src/mongo/db/metadata_consistency_types.idl

+40
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ enums:
4040
values:
4141
kCollectionUUIDMismatch: "CollectionUUIDMismatch"
4242
kCorruptedChunkShardKey: "CorruptedChunkShardKey"
43+
kCorruptedZoneShardKey: "CorruptedZoneShardKey"
4344
kHiddenShardedCollection: "HiddenShardedCollection"
4445
kInconsistentIndex: "InconsistentIndex"
4546
kMisplacedCollection: "MisplacedCollection"
@@ -49,13 +50,15 @@ enums:
4950
kRoutingTableMissingMinKey: "RoutingTableMissingMinKey"
5051
kRoutingTableRangeGap: "RoutingTableRangeGap"
5152
kRoutingTableRangeOverlap: "RoutingTableRangeOverlap"
53+
kZonesRangeOverlap: "ZonesRangeOverlap"
5254

5355
MetadataInconsistencyDescription:
5456
description: "Description of each metadata inconsistency."
5557
type: string
5658
values:
5759
kCollectionUUIDMismatch: "Found collection on non primary shard with mismatching UUID"
5860
kCorruptedChunkShardKey: "Found chunk with a shard key pattern violation"
61+
kCorruptedZoneShardKey: "Found zone with a shard key pattern violation"
5962
kHiddenShardedCollection: "Found sharded collection but relative database does not exist"
6063
kInconsistentIndex: "Found an index of a sharded collection that is inconsistent between different shards"
6164
kMisplacedCollection: "Unsharded collection found on shard different from database primary shard"
@@ -65,6 +68,7 @@ enums:
6568
kRoutingTableMissingMinKey: "Routing table has a gap because first chunk does not start from MinKey"
6669
kRoutingTableRangeGap: "Found a gap between two consecutive chunks"
6770
kRoutingTableRangeOverlap: "Found two overlapping consecutive chunks"
71+
kZonesRangeOverlap: "Found two overlapping zones"
6872

6973
MetadataConsistencyCommandLevel:
7074
description: "Level mode of the metadata consistency command."
@@ -213,6 +217,24 @@ structs:
213217
type: object
214218
description: "The shard key pattern of the collection."
215219

220+
CorruptedZoneShardKeyDetails:
221+
description: "Details about a corrupted zone shard key inconsistency."
222+
strict: false
223+
fields:
224+
namespace:
225+
cpp_name: nss
226+
type: namespacestring
227+
description: "The namespace of the collection."
228+
collectionUUID:
229+
type: uuid
230+
description: "The UUID of the collection."
231+
zone:
232+
type: object
233+
description: "The zone with a corrupted shard key."
234+
shardKeyPattern:
235+
type: object
236+
description: "The shard key pattern of the collection."
237+
216238
HiddenShardedCollectionDetails:
217239
description: "Details about a hidden sharded collection inconsistency."
218240
strict: false
@@ -249,6 +271,24 @@ structs:
249271
type: uuid
250272
description: "The UUID of the collection."
251273

274+
ZonesRangeOverlapDetails:
275+
description: "Details about a zones range overlap inconsistency."
276+
strict: false
277+
fields:
278+
namespace:
279+
cpp_name: nss
280+
type: namespacestring
281+
description: "The namespace of the collection."
282+
collectionUUID:
283+
type: uuid
284+
description: "The UUID of the collection."
285+
zoneA:
286+
type: object
287+
description: "The first zone that overlaps with the second zone."
288+
zoneB:
289+
type: object
290+
description: "The second zone that overlaps with the first zone."
291+
252292
MetadataInconsistencyItem:
253293
description: "Object representing a single metadata inconsistency found in a specific shard"
254294
strict: false

src/mongo/db/s/config/configsvr_check_metadata_consistency_command.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,13 @@ class ConfigsvrCheckMetadataConsistencyCommand final
137137
inconsistenciesMerged.insert(inconsistenciesMerged.end(),
138138
std::make_move_iterator(chunksInconsistencies.begin()),
139139
std::make_move_iterator(chunksInconsistencies.end()));
140+
141+
auto zonesInconsistencies = metadata_consistency_util::checkZonesInconsistencies(
142+
opCtx, coll, _getCollectionZones(opCtx, coll.getNss()));
143+
144+
inconsistenciesMerged.insert(inconsistenciesMerged.end(),
145+
std::make_move_iterator(zonesInconsistencies.begin()),
146+
std::make_move_iterator(zonesInconsistencies.end()));
140147
}
141148

142149
std::vector<ChunkType> _getCollectionChunks(OperationContext* opCtx,
@@ -154,6 +161,12 @@ class ConfigsvrCheckMetadataConsistencyCommand final
154161
repl::ReadConcernLevel::kMajorityReadConcern));
155162
}
156163

164+
std::vector<TagsType> _getCollectionZones(OperationContext* opCtx,
165+
const NamespaceString& nss) {
166+
const auto catalogClient = ShardingCatalogManager::get(opCtx)->localCatalogClient();
167+
return uassertStatusOK(catalogClient->getTagsForCollection(opCtx, nss));
168+
}
169+
157170
NamespaceString ns() const override {
158171
return request().getNamespace();
159172
}

src/mongo/db/s/metadata_consistency_util.cpp

+39-1
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,6 @@ std::vector<MetadataInconsistencyItem> checkChunksInconsistencies(
299299
const auto& uuid = collection.getUuid();
300300
const auto& nss = collection.getNss();
301301
const auto shardKeyPattern = ShardKeyPattern{collection.getKeyPattern()};
302-
const auto configShardId = ShardId::kConfigServerId;
303302

304303
std::vector<MetadataInconsistencyItem> inconsistencies;
305304
auto previousChunk = chunks.begin();
@@ -361,5 +360,44 @@ std::vector<MetadataInconsistencyItem> checkChunksInconsistencies(
361360
return inconsistencies;
362361
}
363362

363+
std::vector<MetadataInconsistencyItem> checkZonesInconsistencies(
364+
OperationContext* opCtx, const CollectionType& collection, const std::vector<TagsType>& zones) {
365+
const auto& uuid = collection.getUuid();
366+
const auto& nss = collection.getNss();
367+
const auto shardKeyPattern = ShardKeyPattern{collection.getKeyPattern()};
368+
369+
std::vector<MetadataInconsistencyItem> inconsistencies;
370+
auto previousZone = zones.begin();
371+
for (auto it = zones.begin(); it != zones.end(); it++) {
372+
const auto& zone = *it;
373+
374+
// Skip the first iteration as we need to compare the current zone with the previous one.
375+
if (it == zones.begin()) {
376+
continue;
377+
}
378+
379+
if (!shardKeyPattern.isShardKey(zone.getMinKey()) ||
380+
!shardKeyPattern.isShardKey(zone.getMaxKey())) {
381+
inconsistencies.emplace_back(makeInconsistency(
382+
MetadataInconsistencyTypeEnum::kCorruptedZoneShardKey,
383+
CorruptedZoneShardKeyDetails{nss, uuid, zone.toBSON(), shardKeyPattern.toBSON()}));
384+
}
385+
386+
// As the zones are sorted by minKey, we can check if the previous zone maxKey is less than
387+
// the current zone minKey.
388+
const auto& minKey = zone.getMinKey();
389+
auto cmp = previousZone->getMaxKey().woCompare(minKey);
390+
if (cmp > 0) {
391+
inconsistencies.emplace_back(makeInconsistency(
392+
MetadataInconsistencyTypeEnum::kZonesRangeOverlap,
393+
ZonesRangeOverlapDetails{nss, uuid, previousZone->toBSON(), zone.toBSON()}));
394+
}
395+
396+
previousZone = it;
397+
}
398+
399+
return inconsistencies;
400+
}
401+
364402
} // namespace metadata_consistency_util
365403
} // namespace mongo

src/mongo/db/s/metadata_consistency_util.h

+10
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "mongo/db/query/plan_executor_factory.h"
3535
#include "mongo/s/catalog/type_chunk.h"
3636
#include "mongo/s/catalog/type_collection.h"
37+
#include "mongo/s/catalog/type_tags.h"
3738
#include "mongo/s/request_types/sharded_ddl_commands_gen.h"
3839

3940

@@ -98,5 +99,14 @@ std::vector<MetadataInconsistencyItem> checkChunksInconsistencies(
9899
const CollectionType& collection,
99100
const std::vector<ChunkType>& chunks);
100101

102+
/**
103+
* Check different types of inconsistencies from a given set of zones owned by a collection.
104+
*
105+
* The list of inconsistencies is returned as a vector of MetadataInconsistencies objects. If
106+
* there is no inconsistency, it is returned an empty vector.
107+
*/
108+
std::vector<MetadataInconsistencyItem> checkZonesInconsistencies(
109+
OperationContext* opCtx, const CollectionType& collection, const std::vector<TagsType>& zones);
110+
101111
} // namespace metadata_consistency_util
102112
} // namespace mongo

0 commit comments

Comments
 (0)