beginner~3h

Isolation & Anomalies

The densest, most interview-tested ACID property. By the end of this chapter you'll be able to name every anomaly, every isolation level, and exactly which levels prevent which anomalies — from memory, not a lookup table.

LevelDefinition
BeginnerIsolation controls how much one transaction can "see" of another transaction's unfinished work while both are running at the same time.
TechnicalIsolation guarantees that concurrently executing transactions produce a result equivalent to some serial (one-at-a-time) execution of those same transactions — the exact strength of that guarantee is tunable via one of four standard isolation levels.
Interview-gradeIsolation is implemented via a spectrum of mechanisms trading correctness for concurrency: pessimistic locking (blocking conflicting transactions), MVCC / snapshot isolation (giving each transaction a consistent point-in-time view without blocking readers), and validation-based concurrency control — the isolation level you choose determines which of the three classic anomalies remain possible.

◆ Story — a food delivery app, three ways

Two things happening "at the same time" in a database can go wrong in exactly three well-known ways. Every one of them has a real, everyday consequence.

Dirty read

Transaction A updates your delivery status to "Out for Delivery" but hasn't committed yet (maybe it's still mid-way through also charging your card). Transaction B — the tracking page you're refreshing — reads "Out for Delivery" and shows it to you. Then Transaction A's payment fails and it rolls back. Your delivery status reverts to "Preparing" — but you already saw, and maybe acted on, information that never actually existed. That's a dirty read: reading another transaction's uncommitted changes.

Non-repeatable read

Within one report-generation transaction, you read your wallet balance twice — once at the start, once at the end, to double-check a calculation. Between those two reads, a completely different, already-committed transaction (someone paying you back) changes your balance. Your two reads within the same transaction disagree with each other. That's a non-repeatable read.

Phantom read

You run "count all my orders over ₹500" twice within one transaction, expecting the same number both times since you're not writing anything yourself. Between the two runs, another transaction (a new order you just placed on a different device) commits a new qualifying row. Your second count is different from your first, even though you never touched anything — a whole new row "phantom" appeared. That's a phantom read.

AnomalyWhat changes between two reads
Dirty readYou read data that was never actually committed at all.
Non-repeatable readThe same row, read twice, has different values.
Phantom readThe same query, run twice, returns a different set of rows.
LevelWhat it guarantees
Read UncommittedAlmost no isolation — can see other transactions' uncommitted changes. Rarely used in practice.
Read CommittedNever see uncommitted data — the default in PostgreSQL, Oracle, and SQL Server.
Repeatable ReadThe same row read twice within a transaction always returns the same value — the default in MySQL/InnoDB.
SerializableThe strictest level — transactions behave exactly as if run one after another in some order.
Isolation LevelDirty ReadNon-Repeatable ReadPhantom Read
Read UncommittedPossiblePossiblePossible
Read CommittedPreventedPossiblePossible
Repeatable ReadPreventedPreventedPossible*
SerializablePreventedPreventedPrevented

▲ Interview trap

*PostgreSQL's Repeatable Read actually prevents phantom reads too, via its specific MVCC snapshot implementation — stricter than the SQL standard technically requires at that level. This is a genuinely popular "gotcha" question: the standard defines a minimum guarantee per level, and specific database engines are free to provide (and often do provide) stronger guarantees than the standard mandates. Always answer "per the SQL standard" first, then mention engine-specific behavior as a follow-up if you know it.

BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; SELECT balance FROM wallets WHERE user_id = 42; -- first read -- ... other work happens here, possibly a slow report calculation ... SELECT balance FROM wallets WHERE user_id = 42; -- guaranteed to match the first read, under REPEATABLE READ COMMIT;
@Transactional(isolation = Isolation.SERIALIZABLE) public void generateFinancialReport(Long accountId) { // every read inside here is guaranteed a fully consistent, non-changing view, // as if no other transaction ran concurrently at all }

💻 Code example

BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; SELECT balance FROM wallets WHERE user_id = 42; -- first read -- ... other work happens here, possibly a slow report calculation ... SELECT balance FROM wallets WHERE user_id = 42; -- guaranteed to match the first read, under REPEATABLE READ COMMIT;
Use caseRecommended levelWhy
Typical CRUD web appRead CommittedGood balance — dirty reads are the most dangerous anomaly and are already prevented; the others are rare and often tolerable.
Financial report, multi-step calculationRepeatable Read or SerializableCorrectness across multiple reads within one transaction matters more than raw throughput.
High-throughput, high-contention counter updatesRead Committed + row-level locking (Chapter 07)Serializable's overhead under heavy contention can tank throughput; targeted locking is often more practical.

▲ Common mistake

Defaulting to SERIALIZABLE "to be safe" everywhere is a common overcorrection — it's the most correct level and also the most expensive, since achieving it typically requires either heavy locking or aborting and retrying transactions that would violate serializability. Use the weakest level that's actually safe for the specific operation, not the strongest level unconditionally.

Want a visual for this concept?

Generate a diagram tailored to “Isolation & Anomalies” — the AI picks whichever visual (flowchart, comparison, sequence, etc.) best fits.

Sign in to generate a visual →

Practice quiz

Next Step

Continue to Durability← Back to all Transaction Mastery chapters