Atomic snapshots are only taken now and then, so every mutation since the last snapshot is still lost on a crash. Today you add a write-ahead log - append each committed INSERT, UPDATE, and DELETE to a file and flush it on commit - so a mutation is durable the instant it returns.
Append every committed mutation as a record to a write-ahead log and flush it to disk before the statement returns.
A snapshot captures the whole database at one moment, but between snapshots the engine is back to living in memory. If a mutation commits and then the process crashes before the next snapshot, that change is gone. The classic fix is a write-ahead log (WAL): a file you append a record to for every mutation, and flush to disk before the statement returns. Now “the statement returned” means “the change is durable,” not “the change is in RAM.”
Each record just has to capture enough to redo the mutation later - logging
the statement’s SQL text is the simplest faithful choice, since re-running it
reproduces the exact change. Only mutations are logged; a SELECT reads nothing
into the log. Records are appended in commit order and never rewritten, so the
log is a precise history of everything committed since the last snapshot - which
is exactly what tomorrow’s startup will replay.
// on each committed mutation, append one record then flush:// append the statement (e.g. its SQL text) as a line to db.wal// f.Sync() // force it to disk before the call returns// a read-only statement (SELECT) logs nothing