Cheat Sheet
A single-page reference for everything WAL. Bookmark this page.
WAL Protocol One-Liner
Section titled “WAL Protocol One-Liner”Log records must be durable on stable storage before the modified data page is written to stable storage. A transaction is committed if and only if its COMMIT record is on stable storage.
ARIES Three Passes
Section titled “ARIES Three Passes”| Pass | Input | Action | Output |
|---|---|---|---|
| Analysis | WAL + last checkpoint | Build ATT (active txns) and DPT (dirty pages) | Redo start LSN, Undo list |
| Redo | WAL from RedoLSN forward | Re-apply all logged changes (idempotent via page-LSN) | All pages reflect committed work |
| Undo | Active txns from Analysis | Roll back uncommitted changes (write CLRs) | Clean state |
Crash → [Analysis] → ATT + DPT → [Redo: WAL forward] → [Undo: active txns backward] → Recovery completeSteal / Force Matrix
Section titled “Steal / Force Matrix”| Force (flush at commit) | No-Force (defer flush) | |
|---|---|---|
| Steal (flush before commit) | ❌ Never used | ✅ ARIES (PostgreSQL, InnoDB) |
| No-Steal (keep dirty until commit) | Shadow Paging | ❌ Impractical |
PostgreSQL WAL Config — Top 10 GUCs
Section titled “PostgreSQL WAL Config — Top 10 GUCs”| GUC | Default | When to Change |
|---|---|---|
wal_level |
replica |
→ logical for CDC |
fsync |
on |
Never turn off |
synchronous_commit |
on |
→ off only for non-critical async workloads |
wal_buffers |
-1 (auto, ~shared_buffers/32) |
→ 64MB if wal_buffers_full rising |
max_wal_size |
1GB |
→ 4–16GB if frequent checkpoints |
min_wal_size |
80MB |
→ 1–2GB to reduce WAL file creation |
checkpoint_completion_target |
0.9 |
Keep at 0.9 (spread checkpoint I/O) |
full_page_writes |
on |
Never turn off (unless atomic page writes confirmed) |
wal_compression |
off |
→ on or lz4 (PG15+) to reduce FPI volume |
wal_log_hints |
off |
→ on if using pg_rewind |
# Quick production templatewal_level = replicafsync = onsynchronous_commit = onwal_buffers = 16MBmax_wal_size = 4GBcheckpoint_completion_target = 0.9full_page_writes = onwal_compression = onSQLite WAL Mode Commands
Section titled “SQLite WAL Mode Commands”PRAGMA journal_mode = WAL; -- Enable WAL modePRAGMA wal_autocheckpoint = 1000; -- Auto-checkpoint every 1000 pagesPRAGMA wal_checkpoint(PASSIVE); -- Non-blocking checkpointPRAGMA journal_size_limit = 67108864; -- Max WAL size (64MB)PRAGMA synchronous = FULL; -- Durability level (FULL/NORMAL/OFF)# Files created in WAL modedatabase.db # Main database (read by readers)database.db-wal # Write-ahead logdatabase.db-shm # Shared memory indexKey Monitoring Queries
Section titled “Key Monitoring Queries”-- WAL generation statsSELECT wal_records, wal_fpi, pg_size_pretty(wal_bytes), wal_buffers_full, wal_write, wal_syncFROM pg_stat_wal;
-- Checkpoint statsSELECT num_timed, num_requested, write_time, sync_time, buffers_writtenFROM pg_stat_checkpointer;
-- Replication slot lagSELECT slot_name, active, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS retainedFROM pg_replication_slots;
-- Current WAL positionSELECT pg_current_wal_lsn(), pg_walfile_name(pg_current_wal_lsn());
-- FPI ratioSELECT round(wal_fpi::numeric / NULLIF(wal_records, 0) * 100, 1) AS fpi_pctFROM pg_stat_wal;# Offline WAL inspectionpg_waldump --verify-checksums --stop-on-error pg_wal/pg_test_fsync -f -s 1 # Test fsync latency on WAL diskfsync vs fdatasync
Section titled “fsync vs fdatasync”| Call | Syncs Data | Syncs Metadata | Speed | Use Case |
|---|---|---|---|---|
fsync() |
✓ | ✓ (size, mtime) | Slower | Full durability |
fdatasync() |
✓ | ✗ | Faster | WAL data (PostgreSQL default) |
RWF_DSYNC |
✓ | ✗ | Fastest (1 syscall) | io_uring linked writes |
PostgreSQL uses fdatasync for WAL (data content matters, not file metadata).
Common Log Record Types
Section titled “Common Log Record Types”| Record Type | Purpose | Example |
|---|---|---|
| INSERT/UPDATE/DELETE | Row-level changes | Heap2 rmgr |
| COMMIT/ABORT | Transaction boundary | Transaction rmgr |
| CHECKPOINT | Recovery starting point | XLOG checkpoint |
| FPI (Full-Page Image) | Entire page snapshot | After checkpoint, first page touch |
| CLR | Compensation Log Record | Undo action during recovery |
| HOT_UPDATE | Heap-Only Tuple update | No index change |
| B-tree split/insert | Index structure change | Btree rmgr |
| MULTIXACT | Multi-transaction ID | Transaction rmgr |
Checkpoint Types
Section titled “Checkpoint Types”| Type | Blocks Writers? | Blocks Readers? | Use |
|---|---|---|---|
| PASSIVE | No | No | Default auto-checkpoint |
| FULL | At end (brief) | No | CHECKPOINT SQL command |
| RESTART | Waits for all | No | SQLite — reset WAL after |
| TRUNCATE | Waits for all | No | SQLite — truncate WAL to 0 |
Quick Quiz: Cheat Sheet
-
State the WAL protocol in one sentence. → Log must be durable before data page; commit = COMMIT record durable.
-
What are ARIES’s three passes? → Analysis (build ATT/DPT), Redo (replay WAL forward), Undo (roll back active txns).
-
What Steal/Force policy does ARIES use? → Steal + No-Force.
-
What GUC should you never turn off? → fsync (and full_page_writes in most cases).
-
What is the difference between fsync and fdatasync? → fsync syncs data + metadata; fdatasync syncs data only (faster, sufficient for WAL).