Course contents
On this page
Lesson 25 of 59

Restart recovery without applying a change twice

Use complete records and repeatable replay to recover a committed transfer.

The logging lesson left a committed transfer partly installed in data files. Recovery can read its log and finish the installation. But recovery is also a program: it may crash before it finishes.

We keep the same simplified model: transactions execute serially, unfinished changes never reach data pages, and storage honors the declared persistence operations. Before serving requests, recovery starts from a valid baseline and replays complete committed transactions in log order. Repairing arbitrary media corruption is a separate problem.

Make replay repeatable

Suppose the log records final values, A = 90 and B = 110. Assigning A = 90 again does not subtract another 10. An operation with the same effect when repeated is idempotent.

  1. Before restart

    Saved A = 90, saved B = 100. T's complete commit decision is in the log.

  2. First recovery attempt

    Set A = 90, then crash before setting B.

  3. Second recovery attempt

    Replay from the same valid baseline and ordered log: set A = 90, then B = 110.

Repeated assignment does not repeat the business transfer. Recovery must complete before ordinary readers see the database.

Blindly replaying “subtract 10” against the current value would produce A = 80 on the second attempt. An engine can use final images, sequence metadata, or other carefully designed redo rules to avoid duplicate effects. The rule must account for later transactions too; replaying an arbitrary old image after newer changes would also be wrong.

Distinguish an incomplete tail from valid history

A crash may leave a partial log record at the end. A log format needs lengths and integrity checks to identify complete records and transaction decisions. Under a defined crash model, recovery can ignore an incomplete trailing record that was never committed.

That does not mean “ignore any bytes we cannot parse.” Unexpected corruption inside required committed history must produce a controlled failure or invoke a repair procedure. Guessing could silently lose acknowledged work.

A checkpoint is a recoverable description of a state from which replay can begin. In a simple stop-the-world design, the engine can save a consistent committed baseline and record which log prefix it includes. Only after that baseline is safely published may older recovery information become unnecessary. More concurrent checkpoint schemes need additional bookkeeping.

Move the crash earlier

The log contains T’s planned values but no complete durable commit record. May recovery install those values in our private-write model?

Require evidence of the decision

No. T has not established a durable commit decision, and its tentative changes were never allowed into the data pages. Recovery leaves them out. If the model allowed unfinished writes to data pages, this answer alone would be insufficient; it would also need to remove or hide those effects.

The recovery test is not merely “the engine starts.” It is “the recovered state matches the promised transaction outcomes,” including after a second interruption.

SQLite’s atomic-commit discussion explains concrete storage assumptions and failure windows. It uses a different protocol; compare the guarantees and ordering, rather than treating our example as its implementation.

Extended reference

The extended chapter preserves the original technical coverage, additional examples, and citations. The explanation above supplies the concepts needed for this page; the reference develops the specialist cases.

Find a section from the original chapter