Skip to content
Dev Dump

ACID Properties

ACID overview

PropertyGuaranteeImplementationFailure Mode
AtomicityAll-or-nothingUndo logs, rollback segmentsPartial writes on crash
ConsistencyValid state transitions onlyConstraints, triggersConstraint violations
IsolationConcurrent txns don’t interfereLocks, MVCCRead anomalies, lost updates
DurabilityCommitted = permanentWAL, fsyncData loss on crash

All operations in a transaction succeed together or roll back entirely. Implemented via undo logs that store pre-modification values.

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;

Crash recovery: If crash occurs mid-transaction, recovery process reads undo log and reverts uncommitted changes.


Transactions move the database between valid states. The DBMS rejects any write violating constraints.

Constraint TypeChecked WhenCost
NOT NULL, CHECKPer-row insert/updateLow
UNIQUE, PRIMARY KEYPer-row (index lookup)Medium
FOREIGN KEYPer-row (parent lookup)Medium-High
DEFERRABLE constraintsAt commitBatch-friendly
ALTER TABLE orders
ADD CONSTRAINT fk_customer
FOREIGN KEY (customer_id) REFERENCES customers(id)
DEFERRABLE INITIALLY DEFERRED; -- checked at COMMIT, not per-row

Concurrent transactions must produce results equivalent to some serial execution order.

AnomalyDescriptionExample
Dirty ReadRead uncommitted dataT1 writes, T2 reads, T1 rollbacks → T2 has garbage
Non-Repeatable ReadSame query, different resultsT1 reads X=5, T2 updates X=10 and commits, T1 reads X=10
Phantom ReadNew rows appear in range queryT1 counts rows WHERE x>5, T2 inserts matching row, T1 recounts
Lost UpdateConcurrent writes overwriteT1 and T2 both read X=5, both write X+1, result is 6 not 7
LevelDirtyNon-RepeatablePhantomImplementation
Read UncommittedNo read locks
Read CommittedLock-based or snapshot per statement
Repeatable Read✗*Snapshot at txn start (MVCC)
SerializableSSI or strict 2PL

*MySQL’s Repeatable Read prevents phantoms via gap locks; Postgres doesn’t.


Committed transactions survive crashes. Implemented via Write-Ahead Logging (WAL).

1. Write change to WAL buffer
2. Flush WAL to disk (fsync)
3. Return "COMMIT OK" to client
4. Apply changes to data pages (async, checkpointing)

Recovery: On crash, replay WAL from last checkpoint. Redo committed txns, undo uncommitted.


See Distributed Transactions for 2PC and Saga patterns.