updated February 28, 2021

Atomic operations in MongoDB

The database systems provide different ways to avoid the data loss if the data is changed by several concurrent threads. We'll see cases when we can lose the data, and how to avoid some of them in MongoDB.

Atomic operation to prevent data losses by overwrites from other thread.

Let's have a bank account with 100 USD on it. Suppose there are 2 concurrent threads adding 10 and 20 USD at the same time. It could happen in this way:

  1. thread 1 reads the account state: 100 USD
  2. thread 2 reads the account state: 100 USD
  3. thread 1 updates the account state to 110 USD
  4. thread 2 updates the account state to 120 USD

So thread 1 update result is lost. How can we fix this? By executing the first thread all operations first then only commands from the second.

In MongoDB an operation is called atomic, when other thread can't access or modify the data till the operation has been done. MongoDB provides atomic $inc field operation: getting and updating the value are done immediately one after another not allowing other threads to read or update the field value.

Note. The atomicity is applied to one value, not the all values that match the update operation.

Document structure for atomic operations.

We'll use the MongoDB feature that db.collection.update() operation is atomic on one document to ensure that people can buy product only if it's available:

db.products.insert({
  name: 'Pencil',
  quantity_in_stock: 3, // current quantity avaialable after orders
  orders: [
    {user_id: 1, quantity: 2},
    {user_id: 4, quantity: 5}
  ]
})

Let's buy 3 pencils if they are available:

    db.products.update(
  {name: 'Pencil', quantity_in_stock: {$gte:3}},
  {
    $inc: {quantity_in_stock: -3},
    $push: { orders: {user_id: 5, quantity: 3} }
  }
)

The update has been done only if the quantity in stock is 3 or more: then the quantity in stock is decreased and the user order is added. MongoDB guarantees that one document match and update is done in atomic way i.e. other threads can't access or update the document in the middle.

Note. The atomicity is applied to one document only, not the many documents even they are updated with the one update call.

Atomic operations and transactions

Atomic operations is another way to keep data consistent, without transactions. MongoDB version 4 also supports transactions but atomic operations perform much faster even they require proper data structures as it was shown in the Stock example.