Atomicity, Isolation & Concurrency in MongoDB

Most popular relational databases today support  “ACID” properties – Atomicity, Consistency, Isolation and Durability.  Developers and DBA’s (Database Administrators) working with relational databases have a good understanding of ACID behavior. However, when working with NoSQL databases like MongoDB, there are some key differences that are important for you to understand. MongoDB offers great flexibility in storage, schema, and scaling, but relaxes some of the ACID properties. It’s essential to understand the differences as you model your data and execute MongoDB commands.

Atomicity

Wikipedia defines “Atomicity”  as follows – “In an atomic transaction, a series of database operations either all occur, or nothing occurs. A guarantee of atomicity prevents updates to the database occurring only partially, which can cause greater problems than rejecting the whole series outright. In other words, atomicity means indivisibility and irreducibility”.

MongoDB write operations are atomic, only at the level of a single document. If you’re modifying multiple subdocuments inside a document the operation is still atomic, but if you’re modifying multiple documents, the operation is not atomic. So, how do you achieve atomic behavior across multiple documents? You need to use a “two-phase commit” pattern to achieve the desired atomicity. Here’s a great example from the MongoDB documentation on how to implement this pattern. The two-phase commit pattern is non-trivial to implement and get right – so make sure multiple document write atomicity is something you want to shoot for.

Isolation

Wikipedia defines “Isolation” as follows –  “In database systems, isolation is a property that defines how/when the changes made by one operation become visible to other concurrent operations”.  There are multiple ways to achieve Isolation with your MongoDB operations, for example:

  1. findAndModifyOperation()” Command

    This is one of the simplest ways to query and modify existing documents. The command can return either the previous values of the documents or the new updated values of the documents. You can also sort the matching documents, upsert and select which fields need to be returned:

    db.collection.findAndModify( {
                                   query: <document>,
                                   sort: <document>,
                                   remove: <boolean>,
                                   update: <document>,
                                   new: <boolean>,
                                   fields: <document>,
                                   upsert: <boolean>
                               } );
  2. “Update if current” Pattern

    This pattern is specified in the  MongoDB documentation. It involves more manual work but gives you more control.

  3. $isolation Operator

    The $isolation operator provides a way to isolate writes to multiple documents. However, the $isolation operator does not provide all-or-nothing gaurantee – you’ll need to use some of the atomicity techniques specified in the first section to achieve that. Also, the $isolation operator does not work for shards. This command used to be called “$atomic” – it has now been correctly renamed to “$isolated”.

Concurrency

MongoDB uses locks to prevent multiple clients from updating the same piece of data at the same time. MongoDB 2.2+ uses “database” level locks. So, when one write operation locks the database, all other write operations to the same database (even if they’re to a separate collection) are blocked waiting on the lock. MongoDB uses  “writer greedy” locks which favor writes over reads. In 2.2+, certain long-running operations can yield their locks.

Thread Safety

Not all of the MongoDB client classes are thread-safe – please refer to the documentation of your specific driver to check if the classes you’re using are thread-safe. For example, in the Java driver, the MongoClient class is thread-safe. So, you can use a single instance of this class across all your threads. Internally, MongoClient uses a connection pool to manage connections to the MongoDB server.

As always, if you have any questions, please reach out to us at support@scalegrid.io.


Dharshan is the founder of ScaleGrid.io (formerly MongoDirector.com). He is an experienced MongoDB developer and administrator. He can be reached for further comment at @dharshanrg


2 Shares
+1
Tweet
Share
Share1
Pin1