Watch keynotes and sessions from MongoDB.live, our virtual developer conference.

How to implement optimistic concurrency

I am new to MongoDB, I’m using the Python driver to work with the database. I’d like to be able to implement optimistic concurrency and was wondering if MongoDB has some built in concurrency checking. I tried to test it by creating a database with a single table with a single entry and do the following

  1. Read the table twice for the same record and store the result into 2 separate objects
  2. Update the same field in each object with different values
  3. Perform 2 update_one() operations

When I run this the second write overwrites the first so it appears to me there is no checking by MongoDB. Can anyone direct me on what I’m doing wrong? Here is a screenshot of the code:

What were you expecting?

You are calling update_one twice, so you are asking mongod to update the same document twice. You are getting both changes. The document you get is the result of applying the 2 updates. What would have worry me is that the result would have been a document with StudyId:2222, since it is the first update_one.

I was hoping that the database would have kept track of writes with and recognised that the second write had changed. What I was looking to find out was if MongoDB itself implements optimistic locking or whether the developer needs to take care of that.

I am not sure what you mean by

as for the mongod, you are doing 2 writes and it does it. The first write has terminated successfully and the second one could proceed and succeeded.

If you want to implement some king of network wide mutex, it can be easily done.

  1. A new field, let’s call it mutex and give it the value 0 to indicate that it is available
  2. In your update query, add ‘mutex : 0’, in your $set add ‘mutex:1’. Only the first of the 2 update_one() will succeed as mutex will be 1 for the 2nd one. Here it is easy to see which one is the 2nd one, but I suspect that you want to do that in multiple threads or processes.
  3. You will need to use the result of update_one to determine which one go in there first.

Hi Steeve, thanks for the input. What I want to achieve is ensure that when a p1 write is performed that it doesn’t overwrite a different write that was performed by p2 in between the time of the p1 read the record and is going to write it. I had been wondering if MongoDB had some mechanism to identify this. I’ve created a function in python that I believe will do what I want to achieve this by adding a version field to each collection that contains the datetime and use the version from the read in the match filter for the update. I also update the record with the current datetime. Here is a copy of the code. Now when I try to perform the second write it checks to see if the modification was successful and if not raises an exception.

The mechanism is the query (name filter in your case) and in the set. Like I wrote only one updateDb() will succeed because only one will have a match because you change the matching value in your $set. Just like I wrote, only one will set mutex:1 because only one will match mutex:0. You are simply using ‘version’ like ‘mutex’ but with a more complex value.

In addition, if matched_count == 0 then modified_count will be 0. If matched_count > 0 then modified_count will be 1 because func is update_one.

So it looks like you got your solution.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.