Data Systems / PAPER 03

After the Power Fails: Crash Consistency and the Meaning of Durable

An observer-based durability contract, explicit persistence dependencies, and a bounded crash-state analysis.

引用本文

本篇为英文原文,其他语言译文尚未提供。

Abstract

Durability is a promise about what an observer may recover after a specified failure, rather than a synonym for a successful write call or a structurally consistent restart. This analytical review separates visibility, atomic recovery, acknowledged persistence, and maintenance of recovery state. Six primary sources supply selected evidence on application persistence properties, SQLite rollback and WAL mechanisms, PostgreSQL write-ahead ordering, Linux synchronization semantics, and bounded black-box crash testing. An explicit three-event model distinguishes durable contents, durable naming, and an externally recorded acknowledgment. Enumerating dependency-respecting crash states shows how ordering constraints eliminate acknowledged but unrecoverable outcomes within that model. A separate redo example demonstrates why the final data page can remain unwritten when a complete durable recovery representation exists. Two reproducible figures present state counts and an assumed group-commit service calculation, neither as failure probabilities nor as measured latency. The review develops a counterexample in which atomic recovery still loses acknowledged work, examines ambiguous errors and multi-file updates, and specifies an oracle-driven evaluation protocol. Its conclusion is a conditional durability contract whose premises can be inspected and tested, with explicit limits on what simulated crashes and finite state exploration establish.

In this paper
  1. Durable is an observer-relative promise
  2. Visibility, atomicity, and persistence diverge
  3. A dependency graph makes promises inspectable
  4. A filename has its own persistence boundary
  5. Rollback journals encode a recoverable past
  6. Redo logs encode a recoverable future
  7. Commit and checkpoint are different transitions
  8. Group commit saves service, not automatically latency
  9. Crash tests need an oracle that survives
  10. Errors are state transitions, not annotations
  11. A reproducible evaluation boundary
  12. The boundary of the conclusion

Durable is an observer-relative promise

A successful write call, an atomic update, and a durable transaction are different claims. A process can observe its own buffered data even though a power failure would remove it. A recovery procedure can return a consistent old state while violating a promise that the new state was already committed. The relevant contract must therefore identify an observer, an acknowledgment event, and the failures after which the acknowledged effect must remain recoverable. Without those details, the word durable has too little content to test.

This review studies local crash durability under a deliberately bounded failure model: a sudden loss of volatile state, followed by recovery from storage that respects declared completed flushes. It does not assume protection against permanent media loss or malicious firmware. Six primary sources connect application persistence properties, SQLite rollback and WAL mechanisms, PostgreSQL WAL ordering, Linux synchronization semantics, and bounded crash testing. A small state-space model illustrates why ordering requirements reduce admissible failure states. Its counts are logical possibilities, not estimated failure frequencies. The argument is that durability should be documented as a chain of evidence from the public acknowledgment to the recoverable representation, with every crossing between layers made explicit.

Visibility, atomicity, and persistence diverge

Pillai and colleagues investigate application-level crash consistency and show why filesystem persistence properties matter to update protocols. Their distinction between atomicity and ordering is particularly useful: a system may require both an operation to survive as a unit and one operation to reach storage before another. The historical study is evidence about its tested systems, not a claim that the same vulnerabilities exist in every present filesystem.

For analytical clarity, define atomic recovery as returning either an allowed old state or an allowed new state. Define acknowledged durability separately: if an external observer has received success, recovery must include the promised new effect. The first property permits losing an acknowledged transaction unless the acknowledgment itself is constrained. This gives a simple counterexample to equating crash consistency with durability. A service could always discard its entire volatile working set and recover the last coherent snapshot; it would remain structurally consistent while losing recent acknowledged changes. An evaluation must therefore preserve an independent history of requests and acknowledgments outside the component being crashed. Checking only whether the recovered database opens successfully misses the central promise to the client.

Sources [1]

A dependency graph makes promises inspectable

The constructed replacement model uses three events. D means the new file contents are durable. N means the intended namespace reference to those contents is durable. A means an external observer has recorded a success acknowledgment. A is not a disk block and is not assumed to be persisted by the crashed service. It marks which externally visible histories must be honored. A crash state is represented by the subset of events that have occurred before the crash.

Without ordering constraints, eight subsets are admitted, three of which contain A without both D and N. Adding D before N and N before A produces a total dependency chain with four allowed prefixes and no acknowledged unrecoverable state. Figure one also shows the intermediate case with only the first ordering edge. The model uses downward-closed sets of a partial order and checks them against an independent prefix construction for the chain. It does not claim that all unconstrained subsets occur equally often or that a real filesystem admits every subset. The point is contractual: removing an ordering edge expands what the application must tolerate unless a lower layer supplies an equivalent guarantee.

A filename has its own persistence boundary

The Linux fsync manual states that synchronizing a file does not necessarily synchronize the containing directory entry. It also documents error returns, including failures reported during synchronization. These are concrete interface facts with direct implications for replacement protocols. Persisting bytes and making the intended name survive are separate obligations. Code that checks only a successful rename or close can therefore confuse present visibility with post-crash recoverability.

A proposed single-file replacement protocol writes a temporary file, checks all writes, synchronizes the file, performs a same-filesystem namespace replacement, synchronizes the relevant directory, and only then acknowledges success. That sequence is a design candidate under an explicitly verified filesystem contract, not a portable proof across every operating system, mount mode, or cross-directory operation. The model abstracts its required ordering rather than implementing the system calls. A real validation must test failures after each step, including short writes, synchronization errors, and recovery from a crash before acknowledgment. Temporary names also need a cleanup policy that does not delete the last recoverable version. Error handling is part of the protocol: returning success after a failed barrier destroys the implication that the ordering graph was intended to establish.

Sources [5]

Rollback journals encode a recoverable past

SQLite's atomic-commit description explains its rollback mode and explicitly separates that mechanism from WAL mode. It places hardware assumptions beside the journal and database flush sequence. That presentation is instructive because a journal file's existence is not by itself a proof of recoverability. Its contents, metadata, ordering relative to overwritten pages, and interpretation during restart all participate in the protocol.

Conceptually, a rollback scheme preserves enough prior information before destructive updates become durable. Recovery must distinguish an incomplete transaction that needs reversal from a committed transaction whose old images can be discarded. The decisive transition may be represented through journal deletion or another documented validity mechanism, and its persistence semantics matter. This manuscript does not simplify every SQLite configuration to one universal sequence. Instead, it proposes tracing the invariant each barrier protects: before an old page can be lost, a recoverable old image exists; before commit can be reported, the new state is recoverable under the journal rule. Those statements can be checked against each failure point. A performance optimization that removes a flush should identify which stronger lower-layer assumption now preserves the same invariant.

Sources [2]

Redo logs encode a recoverable future

PostgreSQL's WAL introduction states the ordering rule that log records describing a data change must reach durable storage before the corresponding data-file change. It explains why redo allows data pages to be written later and why a single WAL flush can serve multiple transactions. This is an introductory rule rather than a complete specification of every PostgreSQL recovery or replication setting, so the manuscript does not infer a universal acknowledgment policy from it.

The constructed redo model has a complete log payload L, a commit marker C, an optional updated page P, and an observed acknowledgment A. Its dependencies require L before C, C before A, and L before P. Enumerating the seven admissible states confirms that every acknowledged state can reconstruct the new pair of application values from L and C, whether P survived or not. The model assumes each component is atomic and the log payload complete; torn records, checksums, transaction interleaving, and log recycling are outside it. If an uncommitted atomic page P survives, the toy recovery permits that in-flight effect to survive rather than inventing an unavailable undo image. This is not a complete transaction-abort or isolation model. Its value is to show why durable data pages are not necessary at each acknowledgment when another durable representation is sufficient. Durability is a recoverability property, not a demand that one particular physical layout already be current.

Sources [4]

Commit and checkpoint are different transitions

SQLite's WAL documentation separates writing changes to a log from checkpointing them into the database. It also describes concurrency and operational constraints specific to that design. The separation matters because a checkpoint is maintenance of the recovery representation, while a commit is a transaction visibility and persistence boundary under the selected settings. A system can have many committed changes that have not yet reached their final data-page locations.

That distinction creates an accounting trap. A short benchmark may report fast commits while leaving a large log and future checkpoint work. Conversely, forcing a checkpoint after every transaction may measure a workload unlike the intended configuration. A durability study should report the state of all required files at the end, the time to reach a declared recovery-ready condition, and restart behavior under retained readers or snapshots. The correct backup set also depends on which files still contain committed information. Copying only the apparent main database file can omit state that is essential at that moment. The proposed protocol therefore treats file inventory and recovery procedure as part of the experimental artifact, rather than assuming that one pathname names the complete durable object.

Sources [3]

Group commit saves service, not automatically latency

The second figure uses an explicit group-commit service model. Assume a flush costs four milliseconds, each transaction contributes 0.1 milliseconds of payload service, and a group fits within one flush. The amortized service per transaction is then 4.1 milliseconds for a group of one and 0.35 milliseconds for a group of sixteen. These are constructed arithmetic values. They do not measure any storage device, predict an application's throughput, or include the time spent waiting for a group to form.

This omission is intentional and consequential. At low arrival rates, waiting for sixteen transactions can dominate response time. At high rates, a group may form naturally while a previous flush is in flight. A maximum waiting interval changes the latency distribution and yields variable group sizes. A proper experiment should record arrival, enqueue, barrier-start, barrier-completion, and acknowledgment timestamps separately. It should also declare whether a timeout or error fails the entire group or permits individually determined outcomes. Grouping can preserve the same durable acknowledgment contract while reducing repeated barrier service; it cannot justify acknowledging before the shared barrier succeeds. The service advantage and the correctness argument must be evaluated independently.

Crash tests need an oracle that survives

The bounded black-box testing work of Mohan and colleagues generates operation workloads within an explicit search bound and checks recovered states after simulated crashes. Its methodological contribution is that small, systematically varied workloads can expose defects that normal successful execution misses. The absence of a discovered defect within a bound should not be promoted to a proof for all workloads, devices, or failure modes.

For an application-level test, the oracle should record the last definitely acknowledged transaction, the possibly in-flight transaction, and the allowed recovery outcomes. Unacknowledged work may or may not survive; automatically calling its survival a bug would confuse durability with cancellation. The oracle also needs to distinguish a crash from an injected I/O error that the application was expected to handle before crashing. Replaying a trace with deterministic identifiers helps detect duplicates and missing operations. After recovery, check semantic invariants and exact acknowledged effects, not merely file existence or checksum validity. A checksum can show that stored bytes are internally intact while those bytes represent the wrong version. The expected version relation must come from an independent history whose own persistence is outside the failure domain under test.

Sources [6]

Errors are state transitions, not annotations

A failed synchronization leaves the application with an epistemic problem: it may not know which subset of preceding writes became durable. Retrying blindly can be correct for an idempotent representation and harmful for a non-idempotent external effect. Returning an ordinary success response is unjustified unless the recovery contract can still be established. Returning an error also does not imply that the operation definitely had no effect. The client needs an uncertainty-aware retry protocol, often with a stable operation identifier and a way to query the eventual result.

This reasoning extends the small state model without pretending to simulate all error semantics. Add an outcome class for unknown commit status, then specify how replay resolves it. A reconstructed transaction history should never manufacture certainty from the absence of a response. For multi-file updates, the protocol must also identify the common decision record that prevents individually durable files from representing incompatible versions. Independent file flushes establish individual persistence, not cross-file atomicity. A test matrix should therefore include interruption between files and between decision-record updates. These cases directly target the gap between a collection of successful system calls and an application-level invariant that remains true after restart.

A reproducible evaluation boundary

The proposed empirical study begins with a pinned application build, filesystem version, mount configuration, device and cache settings, and explicit failure model. It records a small family of update protocols and their expected ordering dependencies. For each generated workload, the harness places crash points around writes, namespace changes, flush completion, acknowledgment, and recovery cleanup. It then restores a clean fixture, replays the same logical operations, and checks the surviving state against the independent oracle.

Results should report tested sequences, crash points, recovered outcomes, and any untested boundaries. Simulated process termination does not equal a power loss, because the operating system may retain dirty cache pages. A virtual block-layer model does not automatically cover a device that violates completed flush semantics. These distinctions should appear in the claim itself, not only in a footnote. Performance runs should use the same durability settings as correctness runs and should include log or journal maintenance. A speed comparison between configurations with different acknowledgment promises is still useful if labeled as a contract comparison, but it cannot establish that one implementation delivers the same durability more efficiently.

The boundary of the conclusion

The executable checks confirm that the declared dependency chain eliminates unsafe acknowledged states in a three-event model, that the chain's ideals equal its prefixes, and that the simplified redo representation recovers every acknowledged transaction in its enumerated state space. The model also preserves the counterexample in which recovery is atomic but an early acknowledgment is lost. None of these checks exercises an actual filesystem or storage device, and the state counts are not empirical probabilities.

The central practical conclusion is to express durability as an implication with named premises: after a specified success acknowledgment, under a specified failure set, recovery produces an allowed state containing the promised effect. Premises include completed barriers, retained recovery information, correct error handling, and the observer's acknowledgment history. Changing any premise changes the claim. This formulation supports both implementation review and meaningful experiments because each dependency has a testable role. It also prevents overclaiming: local crash durability does not imply protection against disk loss, replicated commit does not automatically imply application-level atomicity across services, and a clean restart does not by itself demonstrate that every acknowledged effect survived.

Mathematical model

A(x)⟹x∈Recover⁡(Sf)A(x)\Longrightarrow x\in\operatorname{Recover}(S_f)

(1) If the external observer received success for operation x, every allowed failure state S_f must recover its promised effect; the allowed failure set must be declared.

∀(a,b)∈E:b∈S⟹a∈S\forall(a,b)\in E:\quad b\in S\Longrightarrow a\in S

(2) Admissible crash states S are downward-closed subsets under required event dependencies E; no probability distribution is implied.

D≺N≺AD\prec N\prec A

(3) Constructed replacement dependencies: durable data D, durable namespace N, then externally recorded acknowledgment A.

L≺C≺A,L≺PL\prec C\prec A,\qquad L\prec P

(4) Simplified redo dependencies: complete log L precedes commit marker C and page P; acknowledgment follows C. Atomic components are assumed.

s(g)=c+F/gs(g)=c+F/g

(5) Amortized service milliseconds per transaction for group size g, payload cost c=0.1 ms and one flush F=4 ms; batch-formation wait is excluded.

Reproducible analytical figures

Admissible crash states as dependency edges are added: D=data durable, N=name durable, A=acknowledgment recorded; equal counting is not a failure probability.
Figure 1. D=data durable, N=name durable, A=acknowledgment recorded; equal counting is not a failure probability.

Assumptions: Atomic component persistence; All dependency-respecting subsets allowed; No media corruption

CSV data · Vector figure

Amortizing one assumed flush across a batch: Service model excludes time waiting to form a batch; never interpret it as response latency.
Figure 2. Service model excludes time waiting to form a batch; never interpret it as response latency.

Assumptions: Flush cost 4 ms; Payload service 0.1 ms per transaction; Batch fits one flush

CSV data · Vector figure

Executed finite checks

5 check groups passed. The listed cases validate this model; they are not independent experiments or system benchmarks.

  • Unacknowledged page survival needs no invented undo · 2 cases. The toy model permits an in-flight atomic effect to survive; it does not model full abort semantics.
  • Durable acknowledgment requires both data and name · 12 cases. Enumerates 8 unconstrained and 4 chain-respecting states; counts are possibilities, not probabilities.
  • Independent topological-prefix construction · 4 cases. Order ideals match prefixes of a total chain.
  • Redo recovers each acknowledged transaction · 2 cases. Model log L contains full redo payload; page P is optional.
  • Logical atomicity without durability counterexample · 1 cases. Old consistent state can still violate an early acknowledgment.

Comparison

ModelAdmissible statesAcknowledged but unrecoverable
No dependency edges83
D before N before A40
Simplified redo dependencies70

Proposed validation protocol

  • Pin application, operating system, filesystem, mount, device and cache configuration.
  • Write a precise acknowledgment and allowed-failure contract.
  • Record requests and responses in an independent failure domain.
  • List required persistence dependencies for each update protocol.
  • Generate bounded write, replace, append and multi-file workloads.
  • Inject crashes around each mutation, barrier completion and acknowledgment.
  • Distinguish process crashes, kernel crashes, simulated block failures and real power loss.
  • Recover each fixture and compare semantic effects with the independent oracle.
  • Inject synchronization errors and test idempotent resolution of uncertain outcomes.
  • Measure performance under the identical durability settings and include maintenance work.

Limitations

  • Atomic persistence components and reliable completed flushes are assumptions of the model.
  • The model excludes torn sectors, corrupted media, device firmware bugs and replica failures.
  • State enumeration is finite and provides no probability estimate.
  • No real power interruption or filesystem fault injection was performed.
  • Replacement sequences require validation for the actual filesystem and namespace operation.
  • Official documentation versions and application durability settings may change.

Open research questions

  • Which minimal dependency sets preserve acknowledged durability under a concrete filesystem contract?
  • How should clients resolve uncertain commit status after a synchronization error?
  • Can batching reduce barrier service while maintaining a bounded acknowledgment deadline under bursty arrivals?

Evidence and its boundaries

[1] Application crash consistency depends on filesystem persistence properties, including ordering and atomicity.
Historical vulnerabilities do not establish current behavior of an untested filesystem. Inspected: Abstract; paper Section 1.
[2] Rollback-mode atomic commit depends on explicit journaling, flushing and storage assumptions.
The document explicitly excludes WAL-mode mechanism; no SQLite fault test was run here. Inspected: Sections 1, 2, 3.7, 3.10 and 3.11.
[3] SQLite WAL separates commit from later checkpointing and has distinct operational constraints.
Access-year metadata; mutable documentation is not a pinned implementation version. Inspected: Sections 1 and 2.
[4] WAL records must become durable before the corresponding data-file changes; redo permits deferred page writes.
This introductory rule alone does not specify all recovery, replication or acknowledgment settings. Inspected: 28.3 Write-Ahead Logging.
[5] File synchronization does not necessarily persist its directory entry, and synchronization can fail.
Linux-specific API documentation is not a universal filesystem or device proof. Inspected: DESCRIPTION; RETURN VALUE; ERRORS.
[6] Bounded black-box testing enumerates small operation workloads and simulated crash points to reveal bugs.
A bounded search finding no bug is not proof over all workloads or storage hardware. Inspected: Abstract; original PDF first content page.

References

  1. All File Systems Are Not Created Equal: On the Complexity of Crafting Crash-Consistent Applications
    Thanumalayan Sankaranarayana Pillai, Vijay Chidambaram, Ramnatthan Alagappan, Samer Al-Kiswany, Andrea C. Arpaci-Dusseau, Remzi H. Arpaci-Dusseau. USENIX OSDI (2014). https://www.usenix.org/conference/osdi14/technical-sessions/presentation/pillai
    Source access and scope

    Original USENIX abstract and bibliography, plus original PDF introduction through indexed text.

  2. Atomic Commit In SQLite
    SQLite developers. SQLite documentation (2026). https://www.sqlite.org/atomiccommit.html
    Source access and scope

    Official introduction, hardware assumptions and rollback-journal commit sequence headings and text.

  3. Write-Ahead Logging
    SQLite developers. SQLite documentation (2026). https://www.sqlite.org/wal.html
    Source access and scope

    Official overview and How WAL Works, checkpointing and concurrency passages.

  4. Write-Ahead Logging (WAL)
    PostgreSQL Global Development Group. PostgreSQL 18 documentation (2026). https://www.postgresql.org/docs/18/wal-intro.html
    Source access and scope

    Full short official WAL introduction inspected.

  5. fsync(2) — Linux manual page
    Linux man-pages project. Linux man-pages (2026). https://www.man7.org/linux/man-pages/man2/fsync.2.html
    Source access and scope

    DESCRIPTION, RETURN VALUE and ERRORS inspected in the maintained original manual.

  6. Finding Crash-Consistency Bugs with Bounded Black-Box Crash Testing
    Jayashree Mohan, Ashlie Martinez, Soujanya Ponnapalli, Pandian Raju, Vijay Chidambaram. USENIX OSDI (2018). https://www.usenix.org/conference/osdi18/presentation/mohan
    Source access and scope

    Original USENIX record, abstract and bibliography plus PDF opening methodological description.

Commissioned research review · v1. Cite this review · Original source record · Publication record