«Никакие изменения в данных на диске не должны происходить, пока запись об этом изменении не сохранена в WAL».
сначала пишем лог, потом — данные
Этот принцип гарантирует ACID-свойство Durability (долговечность): даже при аварийном отключении питания СУБД сможет восстановить все зафиксированные транзакции.
-
WAL — это последовательность файлов в каталоге
pg_wal/(в старых версиях —pg_xlog/). -
Каждый файл имеет размер 16 МБ (по умолчанию) и имя вида:
000000010000000000000001это LSN (Log Sequence Number) в шестнадцатеричном виде -
WAL состоит из записей (WAL records), каждая из которых описывает одно атомарное изменение:
- Вставка/удаление строки,
- Обновление индекса,
- Создание таблицы,
- Изменение системного каталога,
- Даже
VACUUMиCHECKPOINT.
Пример WAL-записи:
«На странице 123 файла таблицы 16450 замени 8 байт, начиная со смещения 456, на такие-то данные».
А на диске:
ls -lh $PGDATA/pg_wal/
# Видны файлы по 16 МБКак WAL используется при записи данных?
Рассмотрим UPDATE accounts SET balance = 100 WHERE id = 1;:
- Backend формирует WAL-запись, описывающую изменение.
- Пишет её в
wal_buffers(буфер WAL вshared memory). - Изменяет страницу в
shared_buffers(теперь она «грязная»). - При
COMMIT(еслиsynchronous_commit = on):- Выполняется
fsync()— WAL-запись гарантированно сбрасывается на диск (pg_wal/). - Только после этого клиент получает подтверждение
COMMIT.
- Выполняется
- Сама изменённая страница (
shared_buffers) может быть сброшена на диск позже — например,background writerилиcheckpointer.
Благодаря WAL:
даже если сервер упадёт сразу послеCOMMIT, но до сброса страницы на диск — при перезапуске PostgreSQL прочитает WAL и восстановит изменение.
Восстановление после сбоя (Crash Recovery)
При старте после аварии:
- PostgreSQL читает последнюю контрольную точку (checkpoint) из
pg_control. - Находит соответствующий WAL-файл.
- Проигрывает (replay) все WAL-записи от точки checkpoint’а до конца.
- Все зафиксированные транзакции — применяются (REDO).
- Все незафиксированные — откатываются (UNDO через специальные записи или CLOG).
- Система возвращается в согласованное состояние.
WAL и репликация
- Primary сервер записывает WAL.
- WAL sender процесс отправляет WAL-записи по сети.
- Standby сервер получает их через WAL receiver и применяет локально.
- Результат: точная копия данных на реплике.
Это позволяет делать:
- Hot Standby (чтение с реплики),
- Automatic failover,
- Point-in-Time Recovery (PITR).
| Компонент | Роль |
|---|---|
| Backend | Пишет WAL-записи в wal_buffers при изменениях |
| WAL writer | Асинхронно сбрасывает wal_buffers на диск (pg_wal/) |
| Checkpointer | Пишет запись CHECKPOINT в WAL; позволяет удалять старые WAL-файлы |
| WAL sender / WAL receiver | Передача WAL между серверами (репликация) |
wal_buffers | Буфер WAL в shared memory (по умолчанию — 1/32 от shared_buffers, минимум 64 КБ) |
XLogCtl | Глобальное состояние WAL в shared memory: insert LSN, write LSN, flush LSN |
pg_wal/ | Каталог с WAL-файлами на диске |
pg_control | Служебный файл с метаданными: LSN последнего checkpoint’а, состояние кластера |
Ограничения и нюансы
- WAL не сжимается (в стандартном PostgreSQL).
- При высокой нагрузке на запись — диск для WAL должен быть быстрым (лучше SSD, отдельный от данных).
- Если не настроена архивация или репликация — старые WAL-файлы удаляются автоматически.
- При
synchronous_commit = offвозможна потеря последних транзакций при сбое.