BOOK DEEP READ · Database Internals · Chapter 5

Transaction Processing and Recovery

Database Internals · Ch 5 · Alex Petrov · 2019

中文 →

What is this chapter about?

You tap "send money" on your phone. The spinner turns for half a second, then says success. Somewhere in that half second, the machine room loses power.

The first four chapters were about arranging data so it can be found fast. This one is about something else entirely: what happens when a change is only half made and the lights go out, and what happens when two people edit the same record at the same time. Without this chapter, that elegant index tree is a toy that only works for one user on a machine that never fails.

A strange thing first

You probably assume the data files on disk are the database's master copy, and the log file sitting next to them is a backup. It is the other way round. The log is the master copy, the source of truth; the data files are just a fair copy of it — lose them and you can write them out again from the log. The whole reliability story rests on that inversion.

Why the old world was hard

One: changing one thing means touching several places. A transfer subtracts here and adds there, and those two must both count or neither count — do half and money vanishes.

Two: changes happen in memory, and memory dies with the power. A database cannot make a trip to disk for every byte, so it pulls the pages it needs onto a "desk" in memory, edits them there and writes a batch back later. Cut the power mid-way and everything still on the desk is gone.

Three: writing to scattered spots on disk is agonizingly slow. The records you touched live on page 3, page 700 and page 90,000. Disks hate that kind of hunting around; what they love is writing straight on from where they stopped.

The core idea: one running ledger, and two kinds of lock

Write the ledger first, then touch the master copy. Before changing anything, add a line to a ledger that is only ever appended to, never gone back over: "I am about to change that number on page 700 from 100 to 80." Only once that line is safely on disk may you touch the master copy. The ledger is written straight on from where it stopped, exactly what a disk likes. So committing a transfer means waiting for one ledger line to land — the fair copy can be written out at leisure.

After a crash: replay first, undo second. This is the counterintuitive part. On restart the database does not begin by cleaning up the mess. It picks up the ledger and replays the whole stretch of history exactly as it happened — including the moves it already knows will have to be undone. Only once the world has been restored to the instant before the crash does it go back and undo the transactions that got half a sentence out and never said "I'm done." Laying the floor flat and then moving the furniture is far simpler than doing both at once.

Two completely different kinds of lock. One governs people: it stops you seeing work someone else has only half done, and it stays held for the whole transaction. The other governs hands: a page in memory is being rewritten right now, so another thread would read something half-finished — that one guards a few microseconds and is dropped the moment the edit is over. English calls both of them locks; they are not the same thing at all, and confusing them is the beginner's classic stumble.

What you get, and what it costs

With these in place a database can finally say success and mean it. Not "your money is already in the fair copy," but "this is written into the ledger, and the ledger really is on disk; leave the rest to me, a power cut cannot take it away." The cost hides in that same sentence: if any link in the chain — drive, firmware, filesystem — claims "written" when it has not, every clever design above it collapses together.

One thing to remember

A database's truth is not in its data files, it is in that append-only ledger: write the entry before changing anything, and a commit waits only for that entry to land. After a crash, replay the whole history from the ledger first, then undo the sentences that were never finished. As for concurrency, remember there are two kinds of lock — one guarding the rules between transactions, one guarding a few microseconds on a single page in memory.

Want the mechanisms, the notation and the diagrams? → Switch to the deep read