Правило write-ahead
Любое изменение делается в два приёма: сначала запись об изменении дописывается в журнал и попадает на диск, и только потом (позже) изменённая страница данных. Журнал опережает данные - отсюда «запись с опережением».
Это спасает при сбое: если упали после журнальной записи, но до записи страницы - изменение доиграют из журнала; если до журнальной записи - транзакция не подтверждена, терять нечего.
Почему дёшево
Журнал пишется последовательно, дозаписью в конец одного потока. Последовательная запись на порядки быстрее случайной записи разбросанных по диску страниц. WAL превращает множество мелких случайных записей в одну последовательную, а запись страниц данных откладывает (bgwriter, контрольная точка - см. checkpoint).
LSN
LSN (Log Sequence Number) - смещение в байтах в потоке WAL, тип pg_lsn,
печатается как 16/B374D848. Каждая страница помнит LSN последнего
отражённого в ней изменения (pd_lsn); страницу нельзя записать на диск,
пока журнал не сброшен до её pd_lsn. Разница двух LSN - объём журнала в
байтах.
SELECT pg_current_wal_lsn();
SELECT pg_current_wal_lsn() - '0/0'; -- сколько байт WAL сгенерировано
Durability и synchronous_commit
COMMIT дописывает запись о коммите и ждёт сброса журнала на диск (fsync)
до неё - это буква D в ACID. synchronous_commit = on (по умолчанию)
включает это ожидание; off ускоряет коммит ценой потери хвоста
подтверждённых транзакций при сбое (данные остаются согласованными).
Что пишут и где
Журнал живёт в сегментах pg_wal/ (16 МБ). Пишут бэкенды и walwriter.
Темп виден в pg_stat_wal. Защита от рваной записи - full-page-images;
уровень детализации - wal-level.