Skip to content

Dirty read ​

A dirty read is reading another transaction's uncommitted data. The danger is not that the data is fresh. It's that it may never become real: if the writer rolls back, you have read a value that never became committed. Any external action based on it is hypothetical in this page's illustration; no receiver is executed.

Session A
Session B
BEGIN
BEGIN
UPDATE accounts SET balance = 999
SELECT balance→ 999 ← uncommitted data
ROLLBACK
acts on a balance that never existed

This is an illustrative schedule, not an additional executable Scenario.

Formally this is Adya's G1a (aborted read). Its sibling G1b (intermediate read) is subtler: reading a draft the writer later overwrites before committing; both live in the anomaly catalog with the rest of the G1 family.

Who prevents it ​

LevelSQL standardPostgreSQLMySQL (InnoDB)
READ UNCOMMITTEDpermittedimpossible: the level silently behaves as READ COMMITTEDhappens (proof)
READ COMMITTED and upexcludedM: excluded for concurrent table changesM: excluded for concurrent table changes (contract and examples)

M means Documented contract, distinct from one demonstrated schedule. The scoped isolation contracts exclude other transactions' uncommitted table changes from ordinary consistent reads at READ COMMITTED and stronger levels; own writes and PostgreSQL sequences have separate rules. PostgreSQL accepts READ UNCOMMITTED as READ COMMITTED. InnoDB READ UNCOMMITTED permits the demonstrated dirty value; selecting it requires accepting that risk, not an unmeasured performance promise.

  • Non-repeatable read, the committed-data cousin: nothing you read is dirty, yet repeated reads still disagree.
  • Intermediate read (G1b), the dirty read's nastier variant: a draft value that no committed history ever contained.

See it happen ​

MIT Licensed · Every transcript on this site was generated by a real database run against MySQL 8.4.11 and PostgreSQL 18.6 at 8fa27b8; shared YAML has an independent psycopg/PyMySQL check.