Transactions, ACID & Concurrency

A transaction is a sequence of database operations treated as a single unit: either everything succeeds, or nothing does. Transactions are how databases protect your data from crashes, bugs, and concurrent users stepping on each other.

What is a Transaction?

sql
Loading...

If the server crashes between the two UPDATE statements, the partially-applied transfer would leave Alice's account debited but Bob's not credited — money destroyed. The transaction prevents this: either both updates apply, or neither does.

ACID Properties

Atomicity

The transaction is all-or-nothing. If any statement fails (or the server crashes), the entire transaction is rolled back as if it never happened.

sql
Loading...

Consistency

A transaction takes the database from one valid state to another valid state. All constraints — NOT NULL, UNIQUE, foreign keys, CHECK constraints — must hold after every commit.

sql
Loading...

Isolation

Concurrent transactions behave as if they run serially — they don't see each other's uncommitted changes.

sql
Loading...

Durability

Once a transaction commits, the changes survive crashes. The DB writes a Write-Ahead Log (WAL) to disk before applying changes. On restart, uncommitted WAL entries are discarded; committed ones are replayed.

text
Loading...

Concurrency Problems

Without careful isolation, concurrent transactions cause anomalies:

Dirty Read

Reading uncommitted changes from another transaction. If that transaction rolls back, you read data that never existed.

Non-Repeatable Read

Reading the same row twice within a transaction and getting different values because another transaction committed a change in between.

Phantom Read

Running the same query twice and getting different sets of rows because another transaction inserted or deleted rows in between.

text
Loading...

Isolation Levels

SQL defines four isolation levels, trading consistency for concurrency:

LevelDirty ReadNon-Repeatable ReadPhantom ReadHow
Read UncommittedPossiblePossiblePossibleNo locks
Read CommittedNoPossiblePossibleLock on write, release on read
Repeatable ReadNoNoPossible (MySQL: No)Hold read locks until commit
SerializableNoNoNoFull serial-equivalent execution
sql
Loading...

Most production databases default to Read Committed (PostgreSQL, SQL Server) or Repeatable Read (MySQL InnoDB).

MVCC — Multi-Version Concurrency Control

Modern databases (PostgreSQL, MySQL InnoDB, Oracle) implement isolation using MVCC rather than locking everything:

  • Each row maintains multiple versions with timestamps
  • Writers create new versions; old versions remain for existing readers
  • Readers see a snapshot of the database as of their transaction start time
  • No read-write conflicts — readers never block writers
text
Loading...

Savepoints

You can create named checkpoints within a transaction and roll back to them partially:

sql
Loading...

Deadlocks in the Database

Two transactions can deadlock if each holds a lock the other needs:

sql
Loading...

The database detects this and kills one transaction (the "victim"). The victim's transaction is rolled back automatically — the application should retry.

Prevention: always lock rows in the same order across all transactions.

Python: transactions with psycopg2

python
Loading...

Key Takeaways

  • Transactions are all-or-nothing: COMMIT applies everything, ROLLBACK undoes everything
  • ACID guarantees data integrity across failures and concurrent users
  • Isolation levels trade performance for correctness: higher isolation = fewer anomalies = more locking
  • MVCC lets readers and writers proceed concurrently without blocking each other
  • Database deadlocks are detected automatically; design transactions to avoid them by locking in consistent order