What is a Database Transaction?
Interview Question: "What is a transaction, and why do we need it? What happens if an operation fails halfway through without one, how do Savepoints enable partial rollbacks, and what is the WAL Log-Ahead Rule?"
Think about packing a parachute. You either finish every folding step, or none of them count — there's no such thing as jumping with a half-packed parachute. A database transaction works the same way: a group of changes that either all happen, or none of them do.
Why we need transactions
Take a bank transfer of $100 from Alice to Bob. That's two separate steps:
- Subtract $100 from Alice's account
- Add $100 to Bob's account
Say step 1 finishes, then the server crashes before step 2 runs.
- Without a transaction: Alice's $100 is just gone. It never reached Bob. The database is now wrong.
- With a transaction: on reboot, the database sees step 2 never finished, and undoes step 1 too. Alice gets her $100 back.
BEGIN TRANSACTION;
UPDATE accounts
SET balance = balance - 100
WHERE user_id = 'alice' AND balance >= 100;
-- If the app crashes or throws here:
-- the database aborts and rolls back automatically.
UPDATE accounts
SET balance = balance + 100
WHERE user_id = 'bob';
COMMIT;
The transaction state machine
A transaction moves through five states as it runs:
- Active — statements are running.
- Partially Committed — every statement has run in memory, but hasn't been flushed to disk yet.
- Failed — something went wrong: a check failed, a deadlock, a crash.
- Aborted — the database uses the rollback log to undo every change, back to how things were before
BEGIN. - Committed — changes are safely on disk. From here, nothing can roll this back.
Rolling back just one step: Savepoints
Interviewers like to ask: "Can you undo one failed operation without throwing away the whole transaction?" Yes — with a savepoint, a named checkpoint inside the transaction:
BEGIN TRANSACTION;
INSERT INTO orders (order_id, user_id) VALUES (501, 'alice');
SAVEPOINT payment_attempt;
-- Try a secondary payment method
INSERT INTO payments (order_id, method, status) VALUES (501, 'crypto', 'FAILED');
-- Undo only the failed payment, keep the order
ROLLBACK TO payment_attempt;
-- Fall back to credit card
INSERT INTO payments (order_id, method, status) VALUES (501, 'credit_card', 'SUCCESS');
COMMIT;
Most databases (PostgreSQL, MySQL) don't have true nested transactions — savepoints are how they fake it.
How crash recovery works: the Log-Ahead rule
How does the database guarantee rollbacks and crash recovery always work? With Write-Ahead Logging (WAL):
The rule: before any change is written to the real data file on disk, the database must first write (and confirm) a log entry describing that change.
So if the server crashes mid-transaction, the database reads that log on restart and knows exactly what to do:
- Redo — replay the changes for transactions that had already committed.
- Undo — reverse the changes for transactions that were still in progress.
Say this in the interview
"A transaction is a group of database operations that either all succeed (commit) or all get undone (rollback) — there's no in-between state."
One more thing: auto-commit
By default, most databases (MySQL, PostgreSQL) run in AUTOCOMMIT = ON mode — every single statement is automatically its own mini-transaction. To group several statements into one atomic unit, you have to explicitly wrap them in BEGIN ... COMMIT.