ACID and Transactions
The guarantees your ETL assumes without realizing it
ACID (Atomicity, Consistency, Isolation, Durability) is the contract a single-node or single-partition database keeps. Isolation levels decide which anomalies your concurrent transactions can exhibit.
What you will learn
- Define each ACID property with a failure example
- Predict the outcome of two transactions under each isolation level
- Choose an isolation level from a workload's tolerance for anomalies
What is this?
ACID is a contract a database keeps around each transaction. Atomicity means the transaction all-or-nothing, Consistency means invariants hold, Isolation means concurrent transactions behave like they ran serially (or to the degree you choose), and Durability means an acknowledged commit survives crashes.
Why do you need it?
- Your ingestion process trusts that a failed bulk load rolled back cleanly (atomicity).
- Warehouse snapshots rely on the same isolation level the analytics query thinks it is using.
- REQUIRED motivator: choosing the wrong isolation level is a silent data-integrity bug, the scariest kind.
Mental model
Bank double-entry made with paper, one transaction at a time
ACID serializability
Paper clerks write each transaction fully or strike it out completely (atomic), and never let two tellers edit the same page at once (isolated). The database automates this at web scale.
How it works
- Atomicity is implemented by undo (rollback segments) or versioned row garbage-collected on abort.
- Isolation tracked by locks, MVCC snapshots, or both; PostgreSQL PostgreSQL uses MVCC snapshots plus explicit locks.
- Anomalies: dirty read (read uncommitted), non-repeatable read (values change mid-transaction), phantom (rows appear), write skew (two writers commit a jointly-invalid pair of decisions).
- Isolation ladder: READ UNCOMMITTED < READ COMMITTED < REPEATABLE READ < SERIALIZABLE (most strict but most expensive).
- Postgres treats READ COMMITTED as default and documents that REPEATABLE READ stops phantom re-reads inside one snapshot.
Anomalies across the isolation ladder.
Key commands
SHOW default_transaction_isolation;See the session's isolation level.
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;Raise the strictness for this transaction.
SELECT xmin, xmax, ctid FROM t;Inspect Postgres version metadata that makes MVCC visible.
Examples
Where COMMIT lands
BEGIN;UPDATE balances SET amount = amount - 100 WHERE id = 1;-- until COMMIT:-- - another session cannot see the -100 (atomicity + isolation)-- - a crash here rolls everything backCOMMIT; -- durability: acked only after the WAL is fsyncedEach property is a promise about a different moment: atomicity at the moment of abort, isolation during the flight, durability after the ack.
In production
- A double-spend guard runs SELECT ... FOR UPDATE on the payment account before adjusting it.
- ETL claims 'consistent snapshot' by wrapping a whole table extract in REPEATABLE READ.
- A vaccine appointment system switches to SERIALIZABLE after two concurrent bookings both succeed.
Best practices
- Pick the weakest isolation level that still satisfies your invariant; SERIALIZABLE is notationally nice but competes with latency.
- Use SELECT ... FOR UPDATE for read-modify-write on a row instead of hoping REPEATABLE READ prevents lost updates.
- Keep transactions short; long ones raise deadlock odds and pin MVCC snapshots.
Common mistakes
- Confusing transaction isolation with correct application-level locking (they solve different races).
- Reading a snapshot for an hour then writing based on it — you may be acting on data that changed underneath.
- Assuming REPEATABLE READ means no phantom rows in every database; dialect quirks differ.
Debugging tips
- Reproduce a 'same query, different answers' report by isolating the two sessions and re-running at known isolation levels.
- Check for FOR UPDATE and long transactions when 'leftover data' appears after a bulk load.
- Watch MySQL's and Postgres's documented anomaly matrices; they are subtly different even at the same label.
Interview checkpoint
Hands-on lab
- Reproduce dirty, non-repeatable, and phantom reads by hand
- Watch isolation levels change the outcome
- Demonstrate that SERIALIZABLE stops conflicts or forces a retry
Bob the SQL session hits isolation walls
40 min · advanced
Quick quiz
READ COMMITTED prevents dirty reads but allows non-repeatable reads.
Transaction Q reads a row as 100, waits, reads it again and sees 90 because another transaction committed an update. Which anomaly is this?