Isolation Levels
Isolation levels exist because "concurrent transactions shouldn't interfere with each other" is not a single, fixed rule — it's a spectrum. Stronger isolation gives stronger guarantees about what one transaction can observe of another's in-progress or recently-committed work, but typically at the cost of more blocking or more transactions having to retry. PostgreSQL lets you choose the level a transaction runs at, so you can pick the right trade-off for the task at hand.
Setting the isolation level
BEGIN; SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; -- ... statements run at REPEATABLE READ for this transaction only ... COMMIT;
The levels PostgreSQL supports
Level | Behavior |
|---|---|
Read Committed (default) | Each statement within the transaction sees a fresh snapshot as of when that statement started — so a later statement in the same transaction can see rows committed by other transactions in the meantime |
Repeatable Read | The entire transaction sees one single snapshot, taken as of its first statement — every statement within it sees exactly the same data, no matter what else commits in the meantime |
Serializable | Behaves as if every transaction ran one at a time, in some order — the strongest level; PostgreSQL detects cases where true one-at-a-time behavior couldn't be preserved and forces one of the conflicting transactions to fail and retry |
READ UNCOMMITTED is silently treated as READ COMMITTED instead. This is a genuinely PostgreSQL-specific detail: because of MVCC, a transaction only ever sees committed row versions in the first place, so a true dirty read is architecturally impossible regardless of what isolation level you ask for.Which anomalies each level prevents
Anomaly | Read Committed | Repeatable Read | Serializable |
|---|---|---|---|
Dirty read (seeing uncommitted data) | Prevented | Prevented | Prevented |
Non-repeatable read (a re-read row changes value) | Possible | Prevented | Prevented |
Phantom read (a re-run query returns different rows) | Possible | Prevented* | Prevented |
Serialization anomaly (result inconsistent with any one-at-a-time ordering) | Possible | Possible | Prevented |
REPEATABLE READ also prevents phantom reads, which is actually stricter than the SQL standard technically requires at that level.Choosing a level
Read Committed (default) — each statement sees the latest committed data as of when it runs.
Repeatable Read — the whole transaction sees one consistent snapshot throughout.
Serializable — the strongest level; behaves as if transactions ran one at a time.
PostgreSQL has no true Read Uncommitted — it is treated identically to Read Committed, since MVCC makes dirty reads impossible.
Set the level per-transaction with
SET TRANSACTION ISOLATION LEVEL.