Designing Data-Intensive Applications, session 9

Transactions:
what ACID really means

And the weaker guarantees your database gives you by default.

→ next · ← back · N notes · F full screen

Why transactions exist.

Disks fail, processes crash mid-write, networks drop, clients race each other. A transaction groups reads and writes into one unit that either commits or aborts.

If it aborts, the application can safely retry. Whole classes of partial failure disappear.

Crash halfway throughTwo clients overwrite each otherReading half-finished dataLost connection mid-commit
01

The meaning of ACID

Marketing term, specific guarantees.

Four letters, unevenly useful.

Atomicity

Really abortability: on error, all the transaction’s writes are discarded. Nothing to do with concurrency.

Consistency

Your application’s invariants, like credits equal debits. The database can’t know them, so this one is really yours.

Isolation

Concurrent transactions don’t step on each other. Formally: serializable. In practice often weaker.

Durability

Committed data isn’t forgotten: written to disk and/or replicated. There is no perfect durability.

Retrying aborted transactions isn’t free.

  • The transaction committed, but the network dropped the acknowledgement. A retry runs it twice unless you deduplicate.
  • The error was overload. Retrying makes it worse: back off and limit retries.
  • The error is permanent, like a constraint violation. Retrying is pointless.
  • The transaction had side effects outside the database, like sending an email or calling a bank.
  • The client itself crashes while retrying, and the data is lost.
02

Weak isolation

What “read committed” and “repeatable read” actually promise.

Read committed: no dirty reads, no dirty writes.

Default in PostgreSQL, Oracle, SQL Server. Writes take row locks; reads see the last committed version.

Read skew: a snapshot fixes it.

Lost updates: the read-modify-write trap.

Write skew: two correct decisions, one broken rule.

Pattern: SELECT checks a condition → app decides → write changes the condition. Double bookings, duplicate usernames, double spending.

Lab: which anomalies can happen?

Isolation level:

Now, our system.

Load, modify, save

Where does our JPA code load an entity, change a field in Java, and save it, without @Version or a lock? Those are lost updates waiting to happen.

Check-then-act rules

Which business rules check a condition and then write elsewhere: limits, uniqueness, “only one active settlement run”?

Reports during writes

Do any reports or reconciliation jobs read several tables in separate statements under read committed?

Retries

When a transaction fails, do we retry? Is the operation idempotent if it actually committed?

Next session

Transactions, part 2

Serializability three ways: one thread, two-phase locking, and SSI. Chapter 7.