[SERVER-12018] Multi-update can update same doc more than once Created: 09/Dec/13  Updated: 06/Dec/22  Resolved: 08/Jul/19

Status: Closed
Project: Core Server
Component/s: Querying, Write Ops
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Major - P3
Reporter: Scott Hernandez (Inactive) Assignee: Backlog - Query Team (Inactive)
Resolution: Done Votes: 1
Labels: query-44-grooming
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: File update_only_once_on_move.js    
Issue Links:
Duplicate
is duplicated by SERVER-5820 an update operation may modify a docu... Closed
Related
is related to SERVER-17174 Updates can fail to find document dur... Closed
Assigned Teams:
Query
Operating System: ALL
Participants:

 Description   

If a multi-update yields after updating a document, and that document is moved during the yield (by another update), then it may be retrieved by the update's query and updated again.



 Comments   
Comment by Craig Homa [ 08/Jul/19 ]

This can happen by design in the absence of multi document transactions.

Comment by David Storch [ 05/Jul/19 ]

Flagging for re-triage. Now that we support multi-document transactions, I don't think the query team should enhance the guarantees around multi-updates run outside of transactions.

Comment by J Rassi [ 09/May/14 ]

Verified attached test fails against 2.6.1.

Comment by J Rassi [ 10/Dec/13 ]

The main downside is that now moves are O(number of active cursors on ns).

No, there is no downside here: move already calls invalidate on all of the namespace's active cursors.

Comment by Mathias Stearn [ 10/Dec/13 ]

Discussed solution:

Have Runners maintain a single set of seen DiskLocs per cursor (currently there are several). Add a method to Runner, similar to invalidate to notify runners when documents are moved. If a runner had seen the old loc, it would remove it from its seen set and add the new loc. I think this could also replace the custom seen set used by update that only tracks moves local to the current operation. This would also provide a more efficient implementation of snapshot cursors.

The main downside is that now moves are O(number of active cursors on ns). This could be mitigated by making this an opt-in feature of cursors only used for multi-updates and snapshot cursors since there won't be many of those active at once.

Comment by Scott Hernandez (Inactive) [ 09/Dec/13 ]

Attached is a test which shows the behavior on both 2.4.x and 2.5.x.

Here is the ouput:

sh93722| MongoDB shell version: 2.4.8
sh93722| connecting to: 127.0.0.1/admin
***********************************************
assert: [4] != [1] are not equal : had too many distinct values for x: [ 1, 2, 3, 4 ]
Error: Printing Stack Trace
    at printStackTrace (src/mongo/shell/utils.js:37:15)
    at doassert (src/mongo/shell/assert.js:6:5)
    at Function.assert.eq (src/mongo/shell/assert.js:32:5)
    at ./mongo/jstests/update_only_once_on_move.js:20:12
Mon Dec  9 15:26:21.947 [4] != [1] are not equal : had too many distinct values for x: [ 1, 2, 3, 4 ] at src/mongo/shell/assert.js:7
failed to load: ./mongo/jstests/update_only_once_on_move.js

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