Free tutorials & notes in Hindi & English · Clean code examples · Mobile friendly learning
MySQL + SQL · Lesson 87

Concurrency Control in DBMS

What Is Concurrency Control?

Concurrency means several sessions execute transactions during overlapping time. That parallelism improves throughput, but two correct single-user operations can produce a wrong combined result when they read or modify the same data without coordination.

Faculty definition: Concurrency control is the set of DBMS and application techniques that preserves transaction correctness while allowing safe simultaneous access.

InnoDB combines transactions, multi-version concurrency control (MVCC), isolation levels, row and range locks, constraints and deadlock detection. Application design adds atomic statements, version checks, idempotency and retry logic.

Verified Inventory Lab

DROP TABLE IF EXISTS inventory;
CREATE TABLE inventory (
  product_id INT PRIMARY KEY,
  product_name VARCHAR(60) NOT NULL,
  stock INT NOT NULL,
  version_no INT NOT NULL DEFAULT 1,
  CONSTRAINT chk_stock CHECK (stock >= 0)
) ENGINE = InnoDB;

INSERT INTO inventory VALUES
(10, 'Notebook', 5, 1),
(20, 'Pen Pack', 2, 1);
10 | Notebook | stock=5 | version=1 20 | Pen Pack | stock=2 | version=1

Reset product 10 to stock 5 and version 1 before each independent test. Use two MySQL sessions to reproduce races; a one-session test cannot prove concurrency behavior.

Problems Caused by Uncontrolled Concurrency

ProblemSequenceWrong result
Lost updateA reads 5; B reads 5; both write 4Two sales recorded but stock falls only once
Dirty readB reads A's uncommitted value; A rolls backB acted on data that never became real
Nonrepeatable readB reads a row twice around A's commitSame row changes inside B's unit
PhantomA inserts a row matching B's predicateB's repeated result set gains a row
Write skew or rule raceTransactions validate related rows separatelyCombined business rule becomes false
DeadlockA and B hold locks each other needsOne transaction must be rolled back

Choose a technique for the actual invariant. Raising isolation without understanding the query may add contention but still fail to express the intended business rule.

MVCC, Consistent Reads and Isolation

InnoDB MVCC keeps older row versions through undo information so a plain consistent SELECT can read a snapshot. At READ COMMITTED each consistent read gets a fresh snapshot; at REPEATABLE READ consistent reads normally reuse the snapshot created by the first read.

OperationTypical concurrency behavior
Plain SELECT at READ COMMITTED or REPEATABLE READConsistent nonlocking read from an MVCC snapshot
SELECT FOR SHAREShared locking read; conflicting modifications wait
SELECT FOR UPDATEExclusive-style locking read for records to be changed
UPDATE or DELETELocks affected or scanned index records according to plan and isolation

MVCC improves read/write concurrency, but it does not remove write/write conflicts. Long transactions also retain old versions longer and can increase purge and reconstruction work.

Best First Tool: Atomic Conditional Update

If the business decision can be expressed in one DML statement, avoid the read-calculate-write race.

UPDATE inventory
SET stock = stock - 1
WHERE product_id = 10
  AND stock > 0;

SELECT ROW_COUNT() AS sale_succeeded;
First sale: affected rows=1, stock=4 Second sale: affected rows=1, stock=3

Two concurrent executions serialize their conflicting row updates and each subtracts from the current value. When stock reaches zero, the conditional UPDATE affects zero rows and the application reports “out of stock.”

UPDATE inventory
SET stock = stock - 1
WHERE product_id = 10 AND stock > 0;
-- Require ROW_COUNT() = 1 before recording the order.

For an order that also inserts payment and ledger rows, put the atomic stock update and all required writes in one transaction and roll back if any affected-row check fails.

Pessimistic Control with SELECT FOR UPDATE

Pessimistic locking is appropriate when conflict is likely or a multi-step decision must reserve the current row.

-- Session A
START TRANSACTION;
SELECT stock FROM inventory
WHERE product_id = 10
FOR UPDATE;
-- Returns 5 and locks the record.

UPDATE inventory SET stock = stock - 1
WHERE product_id = 10 AND stock > 0;
COMMIT;

-- Session B's conflicting FOR UPDATE or UPDATE waits,
-- then continues from the committed stock of 4.
  • Start the transaction before the locking read; locking reads require autocommit disabled or an explicit transaction.
  • Lock all required rows in a consistent order.
  • Keep the locked section short and perform no user interaction inside it.
  • Use NOWAIT when immediate failure is useful.
  • Use SKIP LOCKED only for queue-like work because it returns an inconsistent view by design.

Optimistic Control with a Version Column

Optimistic control is useful when conflicts are uncommon and work may happen outside a short database transaction. Each reader keeps the version it saw.

-- Both clients initially read stock=5, version_no=1.

-- Client A
UPDATE inventory
SET stock = 4, version_no = version_no + 1
WHERE product_id = 10 AND version_no = 1;
-- affected rows=1; version is now 2.

-- Client B still submits version 1.
UPDATE inventory
SET stock = 4, version_no = version_no + 1
WHERE product_id = 10 AND version_no = 1;
-- affected rows=0: stale update rejected.
Client A succeeds: stock=4, version=2 Client B conflicts: affected rows=0

After a zero-row optimistic update, reload current data and ask the business workflow whether to recalculate, merge or reject. Do not silently overwrite the newer row.

Technique Selection and Production Checklist

NeedPreferred starting technique
Single counter or stock decrementAtomic conditional UPDATE
Short multi-step decision with likely conflictSELECT FOR UPDATE in one transaction
Long editing form with rare conflictOptimistic version check
Read-only snapshot reportConsistent read at suitable isolation
Parallel job queueIndexed status query with FOR UPDATE SKIP LOCKED
  1. Write the invariant in plain language before choosing a lock.
  2. Use InnoDB, explicit transaction boundaries and database constraints.
  3. Index predicates so locking statements scan and lock fewer records.
  4. Check row counts and unique constraints; never assume an UPDATE succeeded.
  5. Access rows in a consistent order and keep transactions short.
  6. Handle deadlock error 1213 by retrying the complete transaction with a bounded policy.
  7. Treat lock timeout separately because default rollback scope can differ.
  8. Load-test concurrent sessions and monitor lock waits.

Continue to locks and deadlocks and MySQL indexes.

Official References

MVCC, locking-read and rollback behavior were checked against the official MySQL 8.4 manual.

Frequently Asked Questions

What is concurrency control in DBMS?
Concurrency control coordinates overlapping transactions so shared data obeys correctness rules while the database still permits useful parallel work.
How can a lost stock update be prevented in MySQL?
Prefer one atomic conditional UPDATE such as stock = stock - 1 WHERE stock > 0, then require one affected row. Locking or an optimistic version column are alternatives for multi-step logic.
What is the difference between optimistic and pessimistic locking?
Pessimistic locking reserves rows before a change, normally with SELECT FOR UPDATE. Optimistic control allows work to proceed and rejects a stale final UPDATE using a version or previous-value condition.
Does MVCC mean writes never block each other?
No. MVCC lets many plain reads use snapshots without locking rows, but conflicting writes and locking reads still acquire locks and can wait or deadlock.
Should a deadlocked statement or the entire transaction be retried?
InnoDB rolls back the entire deadlock victim transaction, so the application should start that complete logical transaction again with bounded retry handling.
🔗

Share this topic with a friend

यह topic किसी दोस्त को भेजें

Found it useful? Send it to a classmate learning the same thing.

अच्छा लगा? जो दोस्त यही सीख रहा है, उसे भेज दीजिए।

💻 Live Code Editor

This page's programs are ready here — run them, edit them, and learn. No installation needed.
Powered by OneCompiler. The code loads into the editor automatically — press Run to see the output. If the editor does not open, open it in a new tab.