The Dirty Read Problem: Why Read Uncommitted Lets You See Lies

2026-06-15

Every database isolation level except one promises that you'll only ever see committed data. Read Uncommitted breaks that promise. It lets one transaction see the in-flight, unwritten changes of another — and if that other transaction rolls back, you acted on data that never officially existed. This is the dirty read.

Here's the canonical example. Transaction A transfers $500 from Alice to Bob:

Alice had $1000 the whole time. B rejected her based on a balance that never existed. No error was thrown, no log line flagged it — B just silently made a wrong decision on phantom data.

Why does this isolation level even exist? Performance. Read Uncommitted skips read locks entirely, so readers never block on writers. In the 1990s, when row-level locking was expensive and MVCC was rare, this was a real throughput win. Today, most modern databases (Postgres, Oracle, SQL Server with snapshot isolation enabled) use MVCC, which gives you Read Committed for free — Read Uncommitted offers no benefit over Read Committed in Postgres at all (it silently upgrades).

Where it still bites people: MySQL with InnoDB honors Read Uncommitted literally. SQL Server defaults to Read Committed but developers add WITH (NOLOCK) hints "to make reports faster" — that's Read Uncommitted by another name. Reporting dashboards built this way can show numbers that briefly contradict themselves: a sum that doesn't equal its parts because rows were read mid-update.

Rule of thumb: if a decision will be persisted, side-effected, or shown to a user as authoritative, never read it under Read Uncommitted. The performance gain is typically under 5% on MVCC databases and the correctness cost is unbounded. Reserve it for one narrow case: approximate aggregates on monitoring dashboards where "roughly right, very fast" beats "exactly right, slightly slower" and the consumer understands the data is best-effort.

The deeper lesson: isolation levels are not just performance dials. Each one defines a precise set of anomalies you're choosing to tolerate. Dirty reads aren't just stale data — they're data that was never true. That's a fundamentally different category of bug, and one that won't appear in any audit log because nothing actually went wrong on the write side.

See it in action: Check out Everything You Know About Isolation Levels Is Wrong - Read Uncommitted/NOLOCK by Erik Darling (Erik Darling Data) to see this theory applied.
Key Takeaway: Read Uncommitted trades the guarantee that you'll only see real data for a performance win that modern MVCC databases already give you for free.

All newsletters