[SERVER-12694] Upsert atomicity confusion Created: 12/Feb/14  Updated: 19/Feb/14  Resolved: 12/Feb/14

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

Type: Question Priority: Major - P3
Reporter: Remon van Vliet Assignee: Unassigned
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
related to SERVER-10350 Atomicity of Upserts on multi field u... Closed
Participants:

 Description   

There is some confusion about upsert behaviour and its atomicity.

Given the following write :

db.col.update({a:1, b:1}, {$inc: {c:1}}, true)

The expectation is that there should never be more than one document in the database with

{a:1, b:1}

in the collection. Now recently this line was added to the "Warning To avoid inserting the same document more than once, only use upsert: true if the query field is uniquely indexed.". This seems to apply that without such a unique index this behaviour is no longer guaranteed.

Questions :

1) Is this unique index needed and if so why (isn't this atomicity guaranteed by the write lock?)
2) Is the current behaviour different from earlier versions and if so, when has this changed.



 Comments   
Comment by Remon van Vliet [ 12/Feb/14 ]

Hi Scott,

Thanks for your answers. Can you confirm since when this is possible. I'm aware various yielding was present since 1.6 or before (afaik mostly for long running updates/removes and with $atomic disable if wanted) but I'm just about positive this wasn't possible until recently given the vast amount of data we've safely upserted through this pattern without unique indexes. The documentation here : http://docs.mongodb.org/manual/faq/concurrency/#does-a-read-or-write-operation-ever-yield-the-lock seems to confirm that more fancy yielding was added recently.

The only scenario where the above can occur is if the entire update/upsert (including the query part) is not protected by a write lock which seems to be implied in the documentation. It would also seem to be isolated to the upsert case since I'm assuming invoking

update(

{a:1}

, {$inc:{a:1}})

twice cannot result in anything but an

{a:2}

document as a result regardless of unique indexes. Would you be able to go into more detail on why this behaviour is specific to upserts and perhaps more relevant why this seems to be intended behaviour as it is clearly counter intuitive?

EDIT :

{a:3}

->

{a:2}
Comment by Scott Hernandez (Inactive) [ 12/Feb/14 ]

1.) The unique index is required to ensure only one document with the given fields. Queries/writes can yield, and have for a long time (since 1.6 or earlier), and will continue to, to increase concurrency.
2.) This is an update to the docs to be more clear on the restrictions, and behavior which has always (see above) existed.

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