Проблема рваной записи
Страница PostgreSQL - 8 КБ, а диск или ОС пишут блоками поменьше (например, 4 КБ). Если сбой случится прямо во время записи 8-КБ страницы, на диск попадёт её половина: часть новая, часть старая. Это рваная запись (torn page). Обычная WAL-запись («измени байт X на Y») такую страницу не починит - она опирается на то, что страница целая.
Решение: full-page image
При первом изменении страницы после каждой контрольной точки PostgreSQL
пишет в журнал полную копию страницы (FPI), а не дельту. При
восстановлении эта копия кладётся поверх возможно рваной страницы целиком,
и дальше применяются обычные мелкие записи. За это отвечает параметр
full_page_writes (по умолчанию on).
Следствие: всплеск WAL после контрольной точки
Сразу после контрольной точки первые изменения каждой страницы тащат за
собой полную копию - объём журнала подскакивает. Это видно в pg_stat_wal:
SELECT wal_fpi, wal_bytes FROM pg_stat_wal;
wal_fpi - число full-page images; его рост коррелирует с частотой
контрольных точек (см. checkpoint). Слишком частые контрольные точки
раздувают WAL именно через FPI.
CRC: граница целого журнала
Каждая WAL-запись несёт контрольную сумму (CRC). При восстановлении CRC проверяется перед применением записи. Битая или оборванная на полузаписи запись означает: журнал здесь и кончился. Всё до этой точки целостно и применяется, всё после отбрасывается - так восстановление никогда не применит полузапись.
Когда отключают (почти никогда)
full_page_writes = off уменьшает WAL, но при рваной записи оставляет
повреждённую страницу без шансов на восстановление. Отключают только на
хранилищах, гарантирующих атомарную запись страницы целиком, и только
зная это точно. Сам принцип журнала - в wal.