Levels of Isolation
Isolation levels define what one transaction is allowed to observe while other transactions are running concurrently.
The clean mental model:
- MVCC is an implementation technique.
- Isolation level is the behavioral contract.
- Different databases implement the same isolation-level names differently, so always check the specific system.
Common anomalies
Dirty read
A transaction reads data written by another transaction that has not committed yet.
-- T1
BEGIN;
UPDATE products SET stock = stock - 10 WHERE id = 1;
-- not committed yet
-- T2
SELECT stock FROM products WHERE id = 1;
-- if T2 sees T1's uncommitted stock change, this is a dirty readIf T1 rolls back, T2 read a value that never really became part of the database.
Non-repeatable read
A transaction reads the same row twice and sees different committed values because another transaction committed between the two reads.
-- T1
BEGIN;
SELECT price FROM products WHERE id = 1; -- 100
-- T2
UPDATE products SET price = 120 WHERE id = 1;
COMMIT;
-- T1
SELECT price FROM products WHERE id = 1; -- 120 under READ COMMITTED
COMMIT;Phantom read
A transaction reruns the same predicate/range query and sees a different set of matching rows because another transaction inserted, deleted, or updated rows that match the predicate.
-- T1
BEGIN;
SELECT * FROM orders WHERE customer_id = 123; -- 2 rows
-- T2
INSERT INTO orders (id, customer_id) VALUES (456, 123);
COMMIT;
-- T1
SELECT * FROM orders WHERE customer_id = 123; -- 3 rows if phantoms are allowed
COMMIT;Write skew
Two transactions read overlapping data, make individually valid decisions, and write different rows, producing a globally invalid result.
Example rule: at least one doctor must be on call.
Initial state:
Alice on_call = true
Bob on_call = true
T1 sees two doctors on call and sets Alice off call.
T2 sees two doctors on call and sets Bob off call.
Final state:
Alice on_call = false
Bob on_call = falseEach transaction looked correct from its own snapshot, but there is no serial order where both transactions should have been allowed to commit.
1. Read Uncommitted
Weakest isolation. Allows dirty reads.
Most serious MVCC databases do not expose true dirty reads. For example, PostgreSQL accepts the READ UNCOMMITTED name but treats it like READ COMMITTED.
Use this mainly as a theory/interview term.
2. Read Committed
Prevents dirty reads, but allows non-repeatable reads and phantom reads.
MVCC mental model:
- Each statement gets a fresh snapshot of committed data.
- You never read another transaction’s uncommitted write.
- Two
SELECTs inside the same transaction may see different committed data.
Example:
T1 first SELECT sees balance = 100.
T2 updates balance to 200 and commits.
T1 second SELECT sees balance = 200.This is a non-repeatable read, not a dirty read.
PostgreSQL’s default isolation level is READ COMMITTED.
3. Repeatable Read
Prevents dirty reads and non-repeatable reads. In snapshot-based systems, the transaction reads from one stable snapshot.
MVCC mental model:
- The transaction uses a stable snapshot, usually established at the first read.
- Re-reading the same row returns the same version.
- New committed rows from other transactions do not suddenly appear in ordinary snapshot reads.
Example:
T1 first SELECT sees balance = 100.
T2 updates balance to 200 and commits.
T1 second SELECT still sees balance = 100.Important nuance:
- In the SQL standard,
REPEATABLE READis often described as still allowing phantom reads. - PostgreSQL
REPEATABLE READprevents phantom reads for ordinary reads because it uses a stable transaction snapshot. - InnoDB
REPEATABLE READalso uses consistent reads and has additional locking behavior, such as next-key locks for locking reads.
So the interview-safe answer is: “Repeatable Read prevents non-repeatable reads; phantom behavior depends on the database implementation.”
4. Serializable
Strongest isolation level.
Guarantee:
The final committed result must be equivalent to some one-at-a-time ordering of the transactions.
Serializable is stronger than Repeatable Read because a stable snapshot alone does not prevent all anomalies. In particular, snapshot isolation can still allow write skew.
Doctor-on-call example:
Initial state:
Alice and Bob are both on call.
T1 reads: two doctors are on call.
T2 reads: two doctors are on call.
T1 sets Alice off call.
T2 sets Bob off call.Under snapshot isolation / some Repeatable Read implementations, both transactions may commit because they wrote different rows.
Under Serializable isolation, one transaction must be blocked, aborted, or retried because there is no serial order that explains both transactions seeing two doctors on call and both committing.
Modern MVCC databases often implement Serializable as:
- MVCC snapshot visibility
- plus conflict detection, predicate locks, dependency tracking, next-key locks, or similar mechanisms
Application code must be prepared to retry transactions that fail with serialization errors.
Summary table
| Isolation level | Dirty reads | Non-repeatable reads | Phantom reads | Notes |
|---|---|---|---|---|
READ UNCOMMITTED | Allowed in theory | Allowed | Allowed | Often not truly supported by MVCC databases |
READ COMMITTED | Prevented | Allowed | Allowed | Snapshot per statement |
REPEATABLE READ | Prevented | Prevented | Depends on DB | Snapshot per transaction in MVCC systems |
SERIALIZABLE | Prevented | Prevented | Prevented | Equivalent to some serial order; may abort/retry |
Interview answer
Say this:
MVCC keeps multiple row versions so readers can read a consistent snapshot without blocking writers. The isolation level defines which snapshot a transaction sees and what anomalies are allowed. In Read Committed, each statement sees a fresh committed snapshot, so dirty reads are prevented but non-repeatable reads and phantoms can happen. In Repeatable Read, the transaction sees a stable snapshot, so repeated reads are consistent. Serializable is stronger: the database guarantees the final result is equivalent to some serial execution, often by detecting conflicts and aborting one transaction when concurrent reads and writes would create an impossible ordering.