[SERVER-20380] Upsert is not atomic when inserting Created: 11/Sep/15  Updated: 20/Jan/17  Resolved: 14/Sep/15

Status: Closed
Project: Core Server
Component/s: Concurrency, WiredTiger
Affects Version/s: 3.0.6
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Daniel Galinkin Assignee: Ramon Fernandez Marina
Resolution: Duplicate Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: File upsert.js    
Issue Links:
Duplicate
duplicates SERVER-16905 Concurrent upserts to the same non-ex... Closed
duplicates SERVER-14322 Retry on predicate unique index viola... Closed
Related
related to SERVER-16261 Make insert on update (upsert: true) ... Closed
Operating System: ALL
Steps To Reproduce:

Create a file named upsert.js with the following content:

upsert.js

var i;
for(i=0; i<10; ++i) {
  db.upsert.update({a:1}, {$inc:{b:1}}, true);
}

On a Mongo 3.0 WiredTiger setup, run these commands in bash:

mongo --eval "db.upsert.drop()";
for((i=0;i<100;i++)); do mongo  upsert.js & done;
mongo --eval "db.upsert.find().forEach(function(d){printjson(d);})";

This produces something like this:

{ "_id" : ObjectId("55f3359949f88a6cd8a11d7a"), "a" : 1, "b" : 997 }
{ "_id" : ObjectId("55f3359949f88a6cd8a11d7b"), "a" : 1, "b" : 1 }
{ "_id" : ObjectId("55f3359949f88a6cd8a11d7c"), "a" : 1, "b" : 1 }
{ "_id" : ObjectId("55f3359949f88a6cd8a11d7d"), "a" : 1, "b" : 1 }

It should produce something like this:

{ "_id" : ObjectId("55f3359949f88a6cd8a11d7a"), "a" : 1, "b" : 1000 }

Participants:

 Description   

When many upserts happen at the same time, and the queried document does not exist, there should be only one insert, and the rest of the upserts should result in updates to the inserted document.

In Mongo 3.0 with the WiredTiger engine, more than one document gets inserted in this situation. This does not happen on MMAPv1, or on Mongo 2.6.



 Comments   
Comment by Ramon Fernandez Marina [ 15/Sep/15 ]

danielgalinkin@gmail.com, I forgot to add a link to the documentation on upsert that explains this behavior and how to use unique indexes to get the behavior you were expecting. Hope this helps.

Ramón.

Comment by Daniel Galinkin [ 15/Sep/15 ]

Oh, ok. I'll refactor my indexes to make them unique and retry the upserts on the application side, then.

Thanks,
Daniel

Comment by Ramon Fernandez Marina [ 14/Sep/15 ]

danielgalinkin@gmail.com, this issue was previously reported in SERVER-16905 and other tickets; this behavior is currently expected, and users may not have seen it before because it's difficult to trigger with MMAPv1 – but much easier with a document-level locking storage engine like WiredTiger. We've been consolidating these reports under SERVER-14322 , so I'm going to mark this ticket as a duplicate of SERVER-14322 .

When a unique index constraint exists on a field affected by this behavior the application receives an error and should be able to retry, but unfortunately in your case it's not possible to identify the spurious inserts. Please feel free to watch SERVER-14322 for further updates on this issue.

Thanks,
Ramón.

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