Overview
Both are concurrency-control strategies for preventing lost updates when multiple transactions touch the same data, but they differ in when they deal with conflict. Optimistic locking assumes collisions are rare and only performs a version check at commit time, while pessimistic locking assumes collisions are likely and takes an exclusive lock before any read or write proceeds.
Comparison Diagram
Comparison Table
| Aspect | Optimistic Locking | Pessimistic Locking |
|---|---|---|
| Access phase | No lock taken; any transaction can read or begin writing the row immediately | Lock acquired (e.g. SELECT FOR UPDATE) before the transaction reads or writes the row |
| Concurrent access | Other transactions freely read and write the same row in parallel | Other transactions attempting the same row must wait for the lock holder to finish |
| Conflict detection timing | Deferred until commit, via a version number, timestamp, or hash comparison | Not needed as a separate step; the lock physically prevents overlapping access |
| On conflict | Commit is rejected; the transaction is rolled back and typically retried | No conflict occurs; the waiting transaction simply blocks until the lock is released |
| Implementation mechanism | Application-level version column checked in the UPDATE’s WHERE clause | Database-level row or table locks managed by the lock manager |
| Throughput under low contention | High; no blocking overhead when collisions are rare | Lower; locking overhead is paid even when no real conflict would occur |
| Behavior under high contention | Retry storms and wasted work as many transactions repeatedly fail and re-run | Orderly queueing keeps correctness but serializes work and limits parallelism |
| Deadlock risk | None, since no locks are ever held | Possible when transactions acquire multiple locks in inconsistent order |
Key Differences
- Optimistic locking detects conflicts at commit time; pessimistic locking prevents them via upfront locking.
- Optimistic locking never blocks other transactions, it only forces a retry on collision.
- Pessimistic locking holds an exclusive lock for the transaction’s full duration, serializing access to the row.
- Optimistic locking carries no deadlock risk because it never holds locks.
- Pessimistic locking trades raw throughput for predictability when contention is heavy.
When to Use Each
Optimistic Locking
- Read-heavy workloads: Most operations only read data and true write collisions are rare, so avoiding lock overhead maximizes throughput.
- Disconnected or long-lived clients: Web/REST clients may take seconds between fetching and submitting an edit, making it impractical to hold a database lock that whole time.
- Low contention on shared rows: Independent edits, like separate users updating their own profile fields, rarely collide, so version-check retries stay rare.
Pessimistic Locking
- High-contention hotspots: Rows like inventory counters or account balances are hit by many concurrent transactions, where retries under optimistic locking would be constant.
- Expensive-to-redo transactions: When a rollback and retry would waste significant computation or external calls, blocking upfront is cheaper than repeating the work.
- Multi-step critical sections: When several dependent reads and writes must appear atomic to everyone else, holding a lock for the whole sequence avoids partial-state visibility.