Explain Each Letter of ACID
To reverse mutations when an error or cancellation occurs:
🟢 Junior Level
ACID is the foundational acronym describing four core requirements of a transaction management system in a Relational Database Management System (RDBMS). These guarantees ensure data integrity, reliability, and predictable processing:
- A — Atomicity: “All or nothing.” A transaction cannot partially execute. If any single operation within a transaction fails, all preceding mutations are rolled back (ROLLBACK), restoring the database to its pristine pre-transaction state.
- C — Consistency: A transaction transitions the database from one valid (consistent) state to another valid state. All schema constraints (
PRIMARY KEY,FOREIGN KEY,CHECK,NOT NULL,UNIQUE) and domain invariants must be strictly satisfied upon completion. - I — Isolation: Simultaneously executing transactions must not interfere with one another. Each transaction operates under the illusion that it is the sole consumer executing against the database.
- D — Durability: Once a transaction is formally committed (COMMIT), its changes are guaranteed to persist in non-volatile storage and will never be lost, even during sudden power failure, OS crashes, or hardware reboots.
Practical Example: Banking Fund Transfer
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class BankTransferService {
private final AccountRepository accountRepository;
public BankTransferService(AccountRepository accountRepository) {
this.accountRepository = accountRepository;
}
// Atomic transaction: both accounts update, or neither updates
@Transactional
public void transferMoney(Long fromAccountId, Long toAccountId, Double amount) {
// 1. Debit from Account A
accountRepository.withdraw(fromAccountId, amount);
// Simulate an unexpected runtime exception (network drop, overdraft, limit breached)
if (amount > 100_000) {
throw new IllegalStateException("Transfer limit exceeded");
}
// 2. Credit to Account B
accountRepository.deposit(toAccountId, amount);
}
}
Analogy: ACID is like sending a high-value parcel via a secured courier service: the parcel is either delivered in full to the recipient or returned completely to the sender with nothing missing (Atomicity); the package must comply with postal dimensions and legal weight rules (Consistency); couriers handle multiple customer packages in parallel without mixing up box contents (Isolation); and once signed for, the delivery record in the ledger cannot be erased or disputed (Durability).
🟡 Middle Level
Architectural Implementation of ACID Components
| ACID Property | Underlying Engine Mechanism (PostgreSQL / MySQL InnoDB) |
|---|---|
| Atomicity | Undo Logs (MySQL) / Write-Ahead Logging WAL (PostgreSQL) |
| Consistency | Schema Constraints (CHECK, FK, UNIQUE) + Application Business Invariants |
| Isolation | MVCC (Multi-Version Concurrency Control) + Locks (Pessimistic / 2PL) |
| Durability | Write-Ahead Logging (WAL / Redo Log) + System fsync() kernel calls |
1. Atomicity: Mutation Journaling
To reverse mutations when an error or cancellation occurs:
- MySQL (InnoDB): Allocates an Undo Log segment. Prior to modifying any row, its pre-image is written to the Undo Log. On
ROLLBACK, InnoDB iterates backward through the Undo Log, applying inverse deltas to restore original row states. - PostgreSQL: Does not perform in-place updates. A modified row is written as a new tuple version, and the old version is tagged with the modifying transaction’s ID in
xmax. OnROLLBACK, PostgreSQL marks the transaction asABORTEDin the transaction status log (pg_xact). The uncommitted tuple versions are simply ignored by subsequent transactions.
2. Consistency: The Two-Tiered Responsibility Model
Data integrity is maintained through a shared contract between the database and application code:
- Database-Level Consistency: Enforced by declarative constraints:
ALTER TABLE accounts ADD CONSTRAINT chk_positive_balance CHECK (balance >= 0);If an operation violates a
CHECKorFOREIGN KEYconstraint, the engine halts execution with a constraint violation and triggers an automatic rollback. - Application-Level Consistency: Business invariants (such as double-entry bookkeeping, where total debits must equal total credits). The database has no awareness of domain accounting rules; preserving this logic is the responsibility of application services.
3. Isolation: MVCC vs. Lock Contention
Classical concurrency control relied on Two-Phase Locking (2PL), where read queries acquired shared locks that blocked incoming writes. Modern engines implement Multi-Version Concurrency Control (MVCC):
- Writers append new row versions without acquiring read-blocking exclusive locks.
- Readers inspect a point-in-time snapshot of the database established when the statement or transaction began.
- Core Invariant: Readers never block writers, and writers never block readers.
4. Durability: Write-Ahead Logging (WAL)
Directly writing modified 8 KB or 16 KB data pages to random sectors on disk during every commit is prohibitively slow. Modern databases use Write-Ahead Logging (WAL):
- When data changes, mutations are sequentially written to an in-memory WAL buffer.
- When
COMMITis executed, the WAL buffer is synchronously flushed to persistent disk storage using the OS system callfsync(). - The table data pages in memory (
shared_buffersin PostgreSQL,Buffer Poolin InnoDB) remain in a “dirty” state and are lazily flushed to disk in the background by a dedicated Checkpointer process. - If a sudden crash occurs, the engine runs Crash Recovery upon reboot, scanning the WAL log forward to reapply all confirmed transactions (REDO).
🔴 Senior Level
Crash Recovery Internals: The ARIES Algorithm
Enterprise relational crash recovery follows the classic ARIES (Algorithms for Recovery and Isolation Exploiting Semantics) protocol:
- Analysis Phase: Scans the WAL forward from the latest checkpoint to reconstruct the state of the active transaction table and dirty page table at the exact moment of failure.
- Redo Phase: Replays all logged operations forward up to the point of failure (repeating history, including operations belonging to uncommitted transactions) to restore the buffer pool to its exact pre-crash state.
- Undo Phase: Traverses the WAL backwards to roll back the changes of all transactions that were active when the crash occurred and never completed a
COMMIT.
PostgreSQL Heap Bloat vs. MySQL Undo Log MVCC Architecture
- PostgreSQL (Append-Only MVCC): Each tuple stores header fields
xmin(creating transaction ID) andxmax(deleting/updating transaction ID). Executing anUPDATEwrites a brand-new row tuple into the table file (Heap). Dead row versions remain on disk until reclaimed by the VACUUM daemon. High-frequency write workloads suffer from Table Bloat ifVACUUMlags behind. - MySQL InnoDB (Rollback Segments): Performs in-place page updates. The prior row version is displaced into the Undo Tablespace as an undo log record. Concurrent readers reconstruct older snapshots dynamically by traversing the Undo Log chain. Tables do not suffer from row bloat, but long-running transactions prevent undo log pruning, causing the undo log to swell.
Durability Trade-offs in High-Throughput Systems
Executing a physical fsync() on every commit restricts write operations to the IOPS limit of storage hardware.
-- PostgreSQL: Asynchronous Commit
SET synchronous_commit = off;
- Performance Gain: Transactions return success to clients as soon as the write enters the memory WAL buffer without waiting for
fsync(). Write throughput typically increases by $3\times$ to $10\times$. - Trade-off: Relaxes strict Durability. A sudden power outage or OS kernel panic can lose the last 200–600 ms of committed transactions before the
walwriterdaemon flushes the buffer to disk.
4 Tricky Questions
1. What is the fundamental difference between Consistency in ACID and Consistency in the CAP theorem?
Answer: They represent two distinct concepts that happen to share a name:
- ACID Consistency (C-ACID): Local state validity. It guarantees that transactional operations preserve schema constraints (
FOREIGN KEY,CHECK,UNIQUE) and application invariants within a single database instance. - CAP Consistency (C-CAP): Distributed Linearizability (Single-Copy Consistency). It guarantees that all replicas across a distributed cluster observe identical data states simultaneously, such that every read receives the most recent write regardless of which node is queried.
2. Does the Durability guarantee mean that table data files on disk are physically updated upon COMMIT?
Answer:
No.
In relational engines (PostgreSQL, MySQL, Oracle), a COMMIT only guarantees that transaction records are flushed and synced (fsync()) to the Write-Ahead Log (WAL / Redo Log).
The primary table data files (.ibd in MySQL or base/* in PostgreSQL) remain dirty in the RAM buffer pool. They are written to disk asynchronously minutes later during a background checkpoint. Durability is fulfilled because should a crash occur before the checkpoint, the engine recovers and reapplies the changes directly from the persistent WAL during reboot.
3. Does Spring’s @Transactional guarantee all four ACID properties by default?
Answer:
No. The Isolation property is only partially guaranteed by default.
Spring’s @Transactional delegates isolation level configuration to the underlying database engine (Isolation.DEFAULT):
- PostgreSQL and Oracle default to Read Committed.
- MySQL InnoDB defaults to Repeatable Read.
Under Read Committed, concurrent transactions remain susceptible to Non-Repeatable Reads and Phantom Reads. Complete transaction isolation is not achieved unless the developer explicitly specifies Isolation.SERIALIZABLE or enforces pessimistic locking (SELECT FOR UPDATE).
4. What are Deferred Constraints, and how do they interact with ACID Consistency?
Answer:
Relational databases allow constraints to be declared as DEFERRABLE INITIALLY DEFERRED.
Normally, schema constraints (FOREIGN KEY, CHECK) are checked immediately after each individual SQL statement.
When a constraint is marked DEFERRED, the engine permits intermediate violations of constraints inside the boundaries of an active transaction (e.g., creating mutually dependent circular foreign keys between parents and children). Validation is postponed until the transaction issues COMMIT. If constraints remain violated at commit time, the entire transaction is rolled back. This provides transactional flexibility without compromising the final consistency of the database.
🎯 Interview Cheat Sheet
- ACID Core Definitions:
- A — Atomicity: All-or-nothing execution; implemented via Undo Logs / WAL rollbacks.
- C — Consistency: Transitioning between valid states; enforced by constraints (
FK,CHECK,UNIQUE) and business logic. - I — Isolation: Non-interference of concurrent transactions; achieved via MVCC and lock managers.
- D — Durability: Guaranteed permanence of committed data; achieved via Write-Ahead Logging (WAL) and
fsync().
- MVCC Invariant: Readers never block writers; writers never block readers.
- WAL Invariant: Log records are flushed sequentially to disk via
fsync()onCOMMIT; dirty memory pages are flushed asynchronously during checkpoints. - Key Traps:
- Do not confuse ACID Consistency (local constraint validity) with CAP Consistency (distributed linearizability).
- A
COMMITwrites to WAL logs, not directly to main table files. @Transactionalruns at the database default isolation level (Read Committedin PostgreSQL), which permits read anomalies.