[SERVER-13010] Sharded upsert incorrectly errors if _id shard key not in replace spec Created: 03/Mar/14  Updated: 06/Dec/22  Resolved: 11/Jun/18

Status: Closed
Project: Core Server
Component/s: Sharding, Write Ops
Affects Version/s: 2.6.0-rc0
Fix Version/s: None

Type: Bug Priority: Minor - P4
Reporter: Mathias Stearn Assignee: [DO NOT USE] Backlog - Sharding Team
Resolution: Duplicate Votes: 0
Labels: 26qa
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Duplicate
duplicates SERVER-34971 Improve mongoS targeting of replaceme... Closed
is duplicated by SERVER-20635 Write failed with error code 61 and ... Closed
Related
Assigned Teams:
Sharding
Operating System: ALL
Participants:

 Description   

If there is no _id in the replace spec it is copied from the query. Note that non-upsert updates handle this correctly:

> sh.shardCollection('test.sharded', {_id:1})
{ "collectionsharded" : "test.sharded", "ok" : 1 }
> db.sharded.runCommand('update', {updates:[{q:{_id:1}, u:{}, upsert: true}]})
{
        "ok" : 1,
        "nModified" : 0,
        "n" : 0,
        "writeErrors" : [
                {
                        "index" : 0,
                        "code" : 61,
                        "errmsg" : "upsert { q: { _id: 1.0 }, u: {}, upsert: true } does not contain shard key for pattern { _id: 1.0 }"
                }
        ]
}
> db.sharded.runCommand('update', {updates:[{q:{_id:1}, u:{}, upsert: false}]})
{ "ok" : 1, "nModified" : 0, "n" : 0 }

This should only be allowed if sharded on _id, because replace-style updates preserve _id.



 Comments   
Comment by Scott Hernandez (Inactive) [ 25/Sep/15 ]

Part of the problem here is that the update system used to generate a new _id value even if the _id was specified in the query, which has been fixed (since 3.0). At this point that we can allow updates (w/upsert:true) if the query contains an _id field, since that query _id will be used to create the new inserted document.

Comment by Greg Studer [ 05/Mar/14 ]

Above test was with 2.4, in 2.6 upsert does in fact use the same _id. This could be interesting in multiversion scenarios...

Comment by Greg Studer [ 03/Mar/14 ]

It's actually not clear to me that this is something we can support - problem is this:

> db.coll.update({ _id : 1 }, { }, true);
> db.coll.find()
{ "_id" : ObjectId("53176700a2bc4d46c176f14a") }

Upserts generate new _ids in response to this operation, and therefore we can't actually target this correctly in a sharded environment. The shard on which we need to perform the query may not be the shard on which the new _id is placed.

Generated at Thu Feb 08 03:30:21 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.