← Home
🏗Crack System Design with DSA AnimatorSystem DesignNEW
🏗 System Design›Databases & API Data Access

🧾Transactions & Isolation

Transactions give atomicity; isolation level decides which concurrency anomalies you allow.

📌 Key IdeaUse transactions for invariant-preserving multi-step writes. Then choose the weakest isolation level that is still correct for your business rule: too weak risks anomalies, too strong harms throughput.
🧩

Problem it solves

  • Multi-step writes can partially apply on failure, leaving business state inconsistent.
  • Concurrent transactions can observe or create anomalies (non-repeatable reads, write skew, phantoms) that break invariants.
✨

Why It Matters

  • Critical flows like payments, transfers, and inventory reservation depend on strict correctness guarantees.
  • Isolation level choice is a direct trade-off between correctness and throughput under load.
🖼

Visual

🧾 Isolation level choice map
Read Committed
  ✅ default in many systems
  ⚠ non-repeatable reads / phantoms can appear

Repeatable Read
  ✅ stable row reads in txn
  ⚠ phantoms/write-skew risk depends on DB engine

Serializable
  ✅ strongest correctness guarantees
  ⚠ highest contention / retries

Think in anomalies and business invariants, not in level names alone.

✅

When to Use

  • Any operation that must be all-or-nothing (payments, transfer, reservation).
  • Invariants spanning multiple statements/tables (balance, seat count, stock).
  • Concurrent writers where stale reads can violate correctness.
🚫

When NOT to Use

  • Long-running workflows with remote calls inside one DB transaction.
  • Holding transactions open across user think time.
  • Blindly forcing Serializable everywhere without measuring retries/lock waits.
💻

Code Variations

1️⃣ Atomic transfer boundaryjava
@Transactional
public void transfer(long from, long to, BigDecimal amount) {
    accountRepo.debit(from, amount);
    accountRepo.credit(to, amount);
}
Both statements commit together or rollback together.
2️⃣ Explicit isolation for critical flowjava
@Transactional(isolation = Isolation.REPEATABLE_READ)
public OrderSummary checkout(long userId) {
    // stable reads needed while computing totals
    return service.computeAndPersist(userId);
}
Use only where required; avoid raising isolation globally.
3️⃣ Serializable with retry loopjava
for (int i = 0; i < 3; i++) {
  try {
    runSerializableUnitOfWork();
    break;
  } catch (CannotSerializeTransactionException e) {
    backoff(i);
  }
}
Serializable often needs retries under contention.
📊

Isolation levels: what changes in practice

AspectRead CommittedRepeatable ReadSerializable
Dirty reads❌ Prevented❌ Prevented❌ Prevented
Non-repeatable reads⚠ Possible❌ Usually prevented❌ Prevented
Phantoms / write skew⚠ Possible⚠ Engine-dependent❌ Prevented
Throughput impact✅ Best⚠ Medium❌ Lowest / most retries
Typical useDefault OLTPRead-consistency-sensitive flowsCritical invariants
🔀

Common Confusions Cleared Up

Transaction vs Isolation

A transaction gives atomicity and durability boundaries. Isolation level controls visibility/concurrency anomalies while transactions overlap.

Pessimistic lock vs higher isolation

Higher isolation is broad and safer but can hurt throughput. Targeted SELECT ... FOR UPDATE can protect specific rows with less global impact when used carefully.

🎤

Interview Q&A

🧾

Quick Cheat Sheet

Step 1Wrap invariant-preserving writes in one transaction.
Step 2Pick weakest isolation that still prevents bad anomaly.
AvoidHTTP calls/user waits inside transaction.
Production signalsDeadlocks, lock waits, serialization retries.
🔗

Related Topics