[SERVER-32862] sh.addShardToZone() allows unusual (invalid?) chunks to be created Created: 23/Jan/18  Updated: 30/Oct/23  Resolved: 06/Feb/18

Status: Closed
Project: Core Server
Component/s: Sharding
Affects Version/s: 3.4.9, 3.7.1
Fix Version/s: 3.7.2

Type: Bug Priority: Major - P3
Reporter: Ronan Bohan Assignee: Blake Oler
Resolution: Fixed Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
related to SERVER-19171 Shell does not always use extended JS... Closed
related to SERVER-66584 sh.updateZoneKeyRange() does not supp... Closed
related to SERVER-34644 Disable `DollarPrefixedFieldName` che... Closed
Backwards Compatibility: Major Change
Operating System: ALL
Steps To Reproduce:

Spin up a simple shared cluster with mlaunch:

mlaunch --sharded 1 --single

Then run the following commands from the mongo shell:

sh.enableSharding("foo")
sh.shardCollection("foo.bar", { "key" : 1 })
 
sh.addShardToZone("shard01", "zone")
 
# This fails as expected
sh.updateZoneKeyRange("foo.bar", { "key": MaxKey }, { "key": MinKey }, "zone")
 
# But this succeeds and creates odd chunks in the chunks collection
sh.updateZoneKeyRange("foo.bar", { "key": { "$maxKey": 1 } }, { "key": { "$minKey": 1 } }, "zone")

Sprint: Sharding 2018-02-12
Participants:
Case:

 Description   

(This issue may be related to SERVER-10987)

Normally it's not possible to create a key which includes a $ symbol but the following somewhat bizarre (and admittedly contrived) command is accepted and generates really odd chunks:

sh.updateZoneKeyRange("foo.bar", { "key": { "$maxKey": 1 } }, { "key": { "$minKey": 1 } }, "zone")

What was meant of course was the following:

sh.updateZoneKeyRange("foo.bar", { "key": MaxKey }, { "key": MinKey }, "zone")

This second form fails as expected as MaxKey is greater than MinKey, but the first form matches more closely how chunks referencing MinKey and MaxKey are shown in, for example, the output of sh.status()

Running the commands in the 'steps to reproduce' section results in the following 3 chunks being created:

mongos> db.chunks.find({},{_id:0,lastmod:0,lastmodEpoch:0})
{ "ns" : "foo.bar", "min" : { "key" : { "$minKey" : 1 } }, "max" : { "key" : { "$maxKey" : 1 } }, "shard" : "shard01" }
{ "ns" : "foo.bar", "min" : { "key" : { "$maxKey" : 1 } }, "max" : { "key" : { "$minKey" : 1 } }, "shard" : "shard01" }
{ "ns" : "foo.bar", "min" : { "key" : { "$minKey" : 1 } }, "max" : { "key" : { "$maxKey" : 1 } }, "shard" : "shard01" }

And the output of sh.status() is as follows:

[...]
  databases:
	{  "_id" : "foo",  "primary" : "shard01",  "partitioned" : true }
		foo.bar
			shard key: { "key" : 1 }
			unique: false
			balancing: true
			chunks:
				shard01	3
			{ "key" : { "$minKey" : 1 } } -->> { "key" : { "$maxKey" : 1 } } on : shard01 Timestamp(1, 1)
			{ "key" : { "$maxKey" : 1 } } -->> { "key" : { "$minKey" : 1 } } on : shard01 Timestamp(1, 2)
			{ "key" : { "$minKey" : 1 } } -->> { "key" : { "$maxKey" : 1 } } on : shard01 Timestamp(1, 3)
			 tag: zone  { "key" : { "$maxKey" : 1 } } -->> { "key" : { "$minKey" : 1 } }

I have no idea how the balancer will react if it sees these chunk ranges...

Another interesting aspect is the following:

mongos> sh.updateZoneKeyRange("foo.bar", { "key": { "$minKey": 1 } }, { "key": { "$maxKey": 1 } }, "zone")
{
	"code" : 9,
	"ok" : 0,
	"errmsg" : "min: { key: { $minKey: 1.0 } } should be less than max: { key: { $maxKey: 1.0 } }"
}

In this case we're trying to set the range to MinKey -->> MaxKey but the validator rejects it (presumably because the min and max values are documents which are being compared in a binary manner and $minKey is alphabetically greater than $maxKey??)

All of the above tested on MongoDB 3.4.9



 Comments   
Comment by Max Hirschhorn [ 19/May/22 ]

Another interesting aspect is the following:

mongos> sh.updateZoneKeyRange("foo.bar", { "key": { "$minKey": 1 } }, { "key": { "$maxKey": 1 } }, "zone")
{
	"code" : 9,
	"ok" : 0,
	"errmsg" : "min: { key: { $minKey: 1.0 } } should be less than max: { key: { $maxKey: 1.0 } }"
}

In this case we're trying to set the range to MinKey -->> MaxKey but the validator rejects it (presumably because the min and max values are documents which are being compared in a binary manner and $minKey is alphabetically greater than $maxKey??)

For posterity, the "min: { key: { $minKey: 1.0 } } should be less than max: { key: { $maxKey: 1.0 } }" error is expected because the literal object { "$minKey": 1 } compares greater than the literal object { "$maxKey": 1 }. { "$minKey": 1 } a BSON Object (type 0x03). MinKey is the literal MinKey value (type 0xFF). See also SERVER-66584 for some additional clarification.

Comment by Githook User [ 06/Feb/18 ]

Author:

{'email': 'blake.oler@mongodb.com', 'name': 'Blake Oler', 'username': 'BlakeIsBlake'}

Message: SERVER-32862 Prevent zone key field names from possessing invalid prefixes
Branch: master
https://github.com/mongodb/mongo/commit/09390471ac2f63a168175b99b83a7ec7a679fde4

Generated at Thu Feb 08 04:31:31 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.