Databases & Storage · Paper 02 / 05

ARIES: A Transaction Recovery Method Supporting Fine-Granularity Locking and Partial Rollbacks Using Write-Ahead Logging

C. Mohan, Don Haderle, Bruce Lindsay, Hamid Pirahesh, Peter Schwarz

1992 · ACM Transactions on Database Systems · ~14 min read

Read the original paper

Pull the plug on a database mid-write and it must come back with every committed change and none of the uncommitted ones. ARIES is the recipe almost every database uses to do that.

The problem: fast, or safe, pick one

A database makes two promises that fight each other. A committed transaction must survive a crash: the moment the client is told “done”, the change is permanent even if the power fails a microsecond later. And an uncommitted transaction must leave no trace: if the crash comes mid-way, its half-written changes must vanish. The simple ways to keep those promises are slow. Forcing every changed page to disk at commit makes commit as slow as the disk; refusing to write any uncommitted page to disk means a big transaction cannot use the buffer pool at all.

High-performance engines want the opposite policies, which the literature calls steal and no-force: let dirty pages reach disk whenever the buffer manager likes, even before commit, and let commit return before any data page is written. Both are fine for throughput and both make recovery hard, because after a crash the disk may hold uncommitted changes that must be undone and lack committed changes that must be redone. By 1992 every vendor had a recovery scheme; most were slow, limited, or quietly wrong in corner cases. ARIES, from IBM’s Almaden lab, is the one that became the standard.

The idea: write it down first, then repeat history

The foundation is write-ahead logging. Every change is described in a log record, with the values before and after, and the record is appended to a sequential log before the page it describes may be written to disk. Commit means the log is durable up to the commit record, nothing more. The log is cheap because it is sequential, and it is complete because nothing happens that it does not describe.

memory · buffer poolpage A · dirtypage B · dirtypage C · cleandiskdata pagesthe log · append-onlyLSN 1, 2, 3, 4 …① log record first, sequentially② page later, whenever convenientcommit = the log is on disk up to the commit record; no data page needs to be
The two rules. A page may be written only after the log records that explain it; a commit is acknowledged only after the log is on disk. Pages themselves are written whenever convenient, or never.

How it works

Every log record has a log sequence number, and every page carries the LSN of the last record applied to it. That one field answers the question recovery asks thousands of times: has this change reached this page? If the page’s LSN is older than the record, apply it; if not, skip. Recovery runs three passes over the log.

oldcheckpointcrash →analysisforward: which transactions were live, which pages dirtyredoforward: repeat every logged change the disk lacks, losers includedundo← backward: roll back the losers, logging each step as a CLR
The three passes. Analysis rebuilds the tables of live transactions and dirty pages from the last checkpoint; redo replays forward from the oldest dirty page; undo walks the losers backwards.
  1. Analysis reads forward from the last checkpoint to find which transactions were in flight and which pages might be dirty.
  2. Redo reads forward and re-applies every change whose page lacks it, no matter whose transaction it was. The database is now exactly as it was at the crash.
  3. Undo reads backward through the loser transactions and reverses each change, writing a compensation log record for every step. A CLR records that the undo happened and points at the next record to undo, so if the system crashes during recovery, the next recovery skips the work already done instead of undoing an undo.
Try itCrash a database and bring it back

Run the script, flush pages to disk whenever you like (or never), then crash. Recovery must end with T1's committed write present and T2's uncommitted writes gone, whatever you did.

write-ahead log durable to LSN 0
lsntxnrecordon disk
empty
pages
pageon diskin buffer
A10 lsn 0clean
B20 lsn 0clean
staterunning

Two rules make everything else possible. Write-ahead: a page may reach disk only after the log records describing it have. Force at commit: the log is flushed before a commit is acknowledged. Pages themselves may be flushed any time, or never.

The compensation records are the part that justifies the long title. Because undo is logged and never repeated, a transaction can be rolled back partially to a savepoint, locks can be taken on individual records rather than whole pages (two transactions may update different rows on one page, and recovery still sorts them out), and checkpoints can be taken while the system is running rather than halting everything. These were the features the vendors wanted and could not get from earlier schemes.

What it changed

ARIES is in IBM’s DB2, in Microsoft SQL Server, and in spirit in Oracle; MySQL’s InnoDB keeps separate redo and undo logs on the same principles. PostgreSQL uses write-ahead logging but skips the undo pass, because its multi-version storage never overwrites a row in place and an uncommitted row version is simply invisible. SQLite’s WAL mode is the same idea at the scale of a phone. More broadly, the paper made “the log is the truth and the pages are a cache of it” the default mental model, which the next three papers on this list each take somewhere new.

Where you meet it today

  • Every database you run. fsync latency on the log is your commit latency; this is why the log goes on the fastest disk.
  • Replication. Shipping the WAL to a replica is how Postgres streaming replication and MySQL binlog replication work; the log was already the complete story.
  • Change data capture. Debezium and friends read the same log to turn a database into an event stream.
  • Embedded stores. RocksDB, etcd and SQLite all write a WAL before anything else; the design is the same whether the database is a cluster or a file.