Concurrency control is the set of techniques a database management system (DBMS) uses to coordinate simultaneous reads and writes, so multiple operations can run at the same time. Consider a live sale on an e-commerce platform, where two users are looking for headphones. They narrow down on the same product with 90% off—but only one set is left in the inventory.
Both the users see the same screen—“only one left”—and quickly click on “buy” at the same time.
What happens next? Who gets to purchase the item? Does the system place an order for both, or do both get messages that the item is out of stock since both of them tried to purchase it?
The two users are called concurrent users because they’re trying to perform a “concurrent” operation—that is, at the same time.
In this article, we’ll learn what concurrent operations are in a distributed database management system, how to control concurrency and handle situations like the one above, and understand how MongoDB has an edge over other databases for concurrency control in DBMS.
Key takeaways
- Real world applications handle huge volumes of transactions, many of which happen simultaneously.
- For applications to be performant, database systems should be able to handle concurrent transactions in a fair and efficient manner.
- However, concurrent transactions can cause inconsistent data and lost updates due to multiple transactions working on the same data.
- To avoid problems with concurrency, databases follow the principles of ACID, ensuring isolation between transactions.
- Concurrency control can be achieved through locking, snapshot isolation, and many other mechanisms.
- MongoDB provides significant advantages over other databases by combining optimistic concurrency control, multi‑granularity locking, and snapshot isolation, reducing the side effects of concurrency control.
Table of contents
- What is concurrent execution?
- What is a dirty read?
- What is a database transaction?
- What is isolation in ACID?
- What is ACID?
- Why is concurrency control needed?
- What are concurrency control protocols?
- What are concurrency control techniques in DBMS?
- How does concurrency control differ in traditional relational databases vs. document databases (MongoDB)?
- How does MongoDB implement concurrency control?
- Related resources
- FAQs
What is concurrent execution?
In a distributed system, numerous transactions may execute simultaneously (concurrently) on the same data. It’s up to the database management system to control the concurrent transactions so that the data stays consistent.
In our example, inventory should be updated correctly: only one of the users should get the headphones and the other user should be shown an “out of stock” message.
What happens without proper concurrency control? Both the users click on “buy.” Both users complete the transaction. The seller is in trouble, because there was only one set of headphones available—that's both a data integrity and data consistency problem.
What happens with proper concurrency control? Both the users click on “buy.” The entire purchase process is tied together into a single transaction—selecting the product, adding the payment details, adding the address, placing the order, and updating database fields like inventory.
The database system decides what approach to take to ensure a fair transaction and effective concurrency control.
So, when User A clicks “buy,” User B—even though nanoseconds later—cannot purchase, because write operations are allowed for only one of them. Once A completes the purchase, B sees the new data: “out of stock.”
But what if A was trying to purchase with a card, and the card was declined? Will B also lose the chance of purchasing the item?
Under a weak isolation level setting, User B can see the uncommitted inventory update and the product as “out of stock,” even though the item is still available—this is called a dirty read problem.
With the “read committed” isolation setting, B will not see the temporary inventory update until the commit—they should still see “one left” (the last committed state) while waiting for their turn. This is where a user cannot read uncommitted data from another transaction.
What is a dirty read?
A dirty read happens when a transaction reads uncommitted data from another transaction. In the headphones example, User B sees “out of stock” while User A’s payment is still pending. If A’s payment fails, B loses the chance unfairly because the read was based on uncommitted data.
What is a database transaction?
A database transaction is a set of database operations performed together. For example, when a user clicks on a purchase, a set of collections (tables) might need updates or inserts. These multiple operations are not considered separate—they are tied together as one (atomic), so that if any error occurs, all of the operations can be rolled back. This ensures data consistency and integrity.
What is isolation in ACID?
Isolation ensures that the outcome of concurrent transactions is the same as executing them in isolation or sequentially, even when they occur simultaneously—when the isolation level is set to serializable.
In our case, this would ensure only one person gets the headphones, and only if A cancels the order does B get it next. The table below summarizes the different isolation levels that can be set for an application, and what would happen in our example case when each of them is set.
Isolation is a part of ACID properties, which all DBMS systems should comply with.
What is ACID?
ACID is a set of four properties—atomicity, consistency, isolation, and durability—that a database management system (DBMS) guarantees to keep transactions reliable.
Since MongoDB supports ACID-compliant multi-document transactions, all operations within the transaction are either committed together or rolled back together. For a fuller look at each property, go to ACID Properties in DBMS Explained.
Why is concurrency control needed?
Concurrency control measures ensure:
- Safer concurrent transactions: Simultaneous transactions do not interfere with one another while maintaining data correctness. For example, when two users attempt to purchase a product simultaneously, the database ensures that only one transaction successfully updates the inventory.
- Reduced wait time and response time: Wait time is limited when managing conflicting transactions. For example, instead of waiting indefinitely, User B receives an “out of stock” message after User A completes their purchase.
- Better resource utilization: Lock contention, retries, and unnecessary processing are reduced, allowing system resources to be used more effectively.
- Consistent state of data and database: The database reflects valid business rules; for example, inventory never goes below zero, even if two users click “buy” simultaneously.
- No data anomalies: Eliminates dirty reads, lost updates, non-repeatable reads, phantom reads, and overselling.
- Improved system performance: Ensures scalability and reliability in multi-user environments. For example, even with thousands of concurrent buyers during a flash sale, the system processes each transaction correctly while preventing overselling and maintaining consistent data.
What are concurrency control protocols?
Databases use different concurrency control protocols—like lock-based, timestamp-based, and graph-based—to manage simultaneous transactions.
Lock-based protocol
By applying lock to a data item, only one transaction can access the it, preventing other conflicting simultaneous transactions from modifying the database.
There are two primary types of locks:
- Exclusive lock (X): Until the lock is released by the transaction that acquired it, no other transaction can read or write the locked data.
- Shared lock (S): Any transaction can read the data, but cannot modify it, other than the transaction that acquires the lock.
Two-phase locking (2PL)
Two-phase locking (2PL) is a lock-based concurrency control protocol that guarantees conflict-serializable schedules (two or more transactions) are completed one after the other rather than simultaneously.
2PL has two phases:
- Growing phase: The transaction acquires all the locks it needs but may not release any locks.
- Shrinking phase: The transaction releases the locks, but may not acquire new locks, giving way to other transactions.
In a stricter variant, strict two-phase locking (Strict 2PL), a transaction must hold all the locks until all its operations are committed or aborted.
Locks avoid conflict in serializable schedules by allowing only one write to happen at a time on the data.
Deadlocks
Locking can introduce deadlocks, where two or more transactions wait indefinitely for one another to release locks.
In our headphones example, say user A selects headphones and then a mobile phone, and user B selects the same phone and headphones. Now A locks the headphone collection, while B locks the mobile phone’s collection. To acquire the next item in their cart, both wait on each other to release the lock—which never happens, resulting in a deadlock.
A common strategy for preventing deadlocks is to acquire locks in a predefined order. For example, if every transaction always locks the headphone inventory before the mobile phone inventory, circular waiting will not occur.
Another approach is to acquire all required locks before performing any updates. If the transaction cannot obtain every required lock, it releases any acquired locks, aborts, and retries later.
These approaches could hit performance due to long-duration locking of data multiple times.
Rather than making transactions wait for long periods, databases like MongoDB allow transactions to proceed optimistically. If two transactions attempt to modify the same document concurrently, MongoDB detects the write conflict during execution or commit. One transaction successfully commits, while the conflicting transaction is aborted with a WriteConflict error and can be safely retried by the application.
Timestamp-based protocol
The timestamp-based protocol assigns a unique timestamp to every transaction and executes conflicting operations as per the timestamp order. If a transaction violates this order, it’s aborted and restarted, ensuring serializability without relying on locks.
Graph-based protocol
The graph-based protocol organizes data items into a directed graph. Transactions follow a predefined traversal order to acquire locks. As transactions acquire locks in the same direction, there are no circular waits, thus preventing deadlocks.
What are concurrency control techniques in DBMS?
The main concurrency control techniques are below.
Optimistic concurrency control (OCC)
OCC lets transactions proceed without locks, checking for conflicts only at commit time. It assumes that conflicts between concurrent transactions are relatively rare. Thus, no locks are applied initially, allowing multiple transactions to read the same data. It’s only during the commit that the database checks whether there is a conflict, and if there is, rolls back the uncommitted transaction.
MongoDB uses OCC, which improves database performance and reduces locking times. The conflicting transaction receives a WriteConflict error when trying to commit and can be safely retried by the application.
Pessimistic concurrency control (PCC)
In the PCC approach, the transaction acquires a lock before reading or modifying data—an S lock for reading and X lock for writing. The transaction releases the lock only after the operation is complete, maintaining data integrity, as other transactions either wait or abort (lock-based protocols). This approach prevents inconsistent data reads, but can reduce the amount of simultaneous operations and create potential deadlocks.
Multiversion concurrency control (MVCC)
MVCC manages concurrent access by keeping multiple timestamped versions of data instead of using read-write locks. Rather than overwriting the same value, when a change occurs the database creates another timestamped version of the document/record. All other transactions read the previous consistent snapshot of the database, allowing concurrent access to multiple users. This approach minimizes the need for locks, managing concurrency without degrading the database performance.
MongoDB does use MVCC, but a bit differently. The WiredTiger engine provides snapshot isolation for transactions, using timestamps and internal history to decide which version of the data a transaction should view. The application does not deal with multiple versions of database objects. This way, MongoDB achieves several benefits associated with MVCC while following a different internal implementation.
How does concurrency control differ in traditional relational databases vs. document databases (MongoDB)?
In a relational database, a transaction is spread across several normalized tables that must all be locked, whereas MongoDB embeds related data in a single document, reducing the need for multi-object locking.
Let's continue our headphones example, where User A purchases the headphones. A typical relational database might have the following normalized tables as per the database schema.
CustomerOrder
OrderLineItems
Inventory
Payment
Customer
One or more rows of all these tables would have to be locked until the transaction is completed. This also blocks these tables from other transactions wanting to access it.
In MongoDB however, all the related data is embedded into a single document—so the majority of the above objects will be included. If all the details cannot be captured, the most frequently accessed details can be stored as a snapshot from the main collection. In the below example, except for Inventory, all the other details required by the transaction are in one single document.
This flexibility in the data model reduces the need for heavy, multi-object locking, drastically minimizing transaction overhead and avoiding the coordination of massive multi-row updates.
How does MongoDB implement concurrency control?
MongoDB implements concurrency control by combining optimistic concurrency control, document-level locking, write-conflict detection, and snapshot isolation.
Let’s continue with the headphones example to see how MongoDB handles simultaneous transactions:
User A and User B read the same data; reads are non-blocking; MongoDB uses snapshot isolation and intent/shared locks that don’t block other readers and writers.
User A’s transaction starts:
MongoDB places intent exclusive (IX) lock on the database as well as the collection. By applying an intent lock, the transaction conveys that it “intends to acquire a lock at the lower (document) level.”
WiredTiger acquires X lock on the document that represents inventory of the headphones.
The transaction writes the new data and commits.
At the same time, User B’s transaction starts.
B sees a consistent snapshot of the database (provided by WiredTiger) and acquires the IX lock on the same.
When B tries to acquire the X lock on the document, MongoDB sees that the document is either locked or updated, hence the operation is aborted.
When the same transaction is retried, user B sees the new inventory value (zero) correctly.
In case A was not able to place the order for some reason (credit card declined), no conflict will be detected and B can complete the transaction seamlessly.
Using a combination of OCC, document-level locking, write-conflict detection, and snapshot isolation, MongoDB significantly reduces the problem of dirty reads, phantom reads, deadlocks, and long-period locking, and isolates transactions smoothly and efficiently.
Phantom read
A phantom read occurs when the same query executed multiple times within a transaction returns a different set of rows or documents because another concurrent transaction has inserted, deleted, or updated data that changes the query results. Phantom reads can be avoided using snapshot isolation.
Related resources
Learn about concurrency — See how MongoDB uses multi-granularity locking and optimistic concurrency control to manage simultaneous read and write operations.
What are database transactions? — Learn how database transactions group multiple read and write operations together to ensure they either succeed completely or fail gracefully as a single unit.
ACID transactions with MongoDB — Explore how to enforce multi-document consistency in replica sets and sharded clusters using standard ACID compliance rules.


