Checkpointer — это один из ключевых фоновых процессов PostgreSQL, который периодически сбрасывает «грязные» (изменённые) страницы из shared_buffers на диск и фиксирует контрольную точку (checkpoint) в WAL.
Checkpoint в WAL — это специальная запись, которая маркирует момент времени, до которого все изменения данных уже гарантированно записаны на диск (в основные файлы таблиц и индексов).
Его главная цель — ограничить объём WAL, необходимый для восстановления после сбоя, и поддерживать стабильную производительность записи.
PostgreSQL использует Write-Ahead Logging (WAL): Пишет «Сначала — в WAL, потом — в данные». Но при этом:
- Изменённые страницы сначала попадают в
shared_buffers(в ОЗУ). - Позже (асинхронно) background writer и checkpointer сбрасывают их на диск.
1. Сброс грязных страниц на диск
- Когда backend изменяет данные, он:
- Модифицирует страницу в
shared_buffers→ страница становится грязной (dirty), - Пишет запись в WAL.
- Модифицирует страницу в
- Сама страница на диск не сбрасывается сразу — это делает Checkpointer (или
background writer). - Checkpointer проходит по всем грязным страницам и записывает их в соответствующие файлы в
base/...
2. Создание контрольной точки (CHECKPOINT)
- После того как все грязные страницы (на момент начала checkpoint’а) сброшены, Checkpointer:
- Пишет специальную запись
CHECKPOINTв WAL, - Обновляет файл
pg_control— фиксирует:- LSN (Log Sequence Number) последнего завершённого checkpoint’а,
- ID временной шкалы (timeline),
- Состояние кластера.
- Пишет специальную запись
Это точка восстановления: при старте после сбоя PostgreSQL будет проигрывать WAL только с этого LSN.
3. Освобождение старых WAL-файлов
- После checkpoint’а WAL-файлы, предшествующие LSN checkpoint’а, считаются ненужными для crash recovery.
- PostgreSQL может безопасно удалить их из
pg_wal/(если они не нужны для репликации или архивации).
Когда запускается Checkpointer?
- По расписанию — каждые
checkpoint_timeoutсекунд (по умолчанию — 5 минут). - По объёму WAL — если накопилось
max_wal_size(по умолчанию — 1 ГБ), запускается ранний checkpoint (spread checkpoint). - Принудительно — при
CHECKPOINTSQL-команде илиpg_ctl checkpoint.
Взаимодействие с другими компонентами
| Компонент | Взаимодействие |
|---|---|
| shared_buffers | Читает грязные страницы для сброса на диск |
| WAL (XLogCtl) | Пишет запись CHECKPOINT, читает текущий LSN |
| pg_control | Обновляет метаданные: checkPoint, checkPointCopy |
| Background writer | Делает «лёгкую» предзапись; Checkpointer — финальный сброс |
WAL files (pg_wal/) | Определяет, какие WAL можно удалить после checkpoint’а |
| Replication slots | Учитывает restart_lsn слотов — не удаляет WAL, нужный репликам |
Ключевые параметры, влияющие на Checkpointer
| Параметр | По умолчанию | Роль |
|---|---|---|
checkpoint_timeout | 5min | Максимальный интервал между checkpoint’ами |
max_wal_size | 1GB | При превышении — ускоряется checkpoint |
checkpoint_completion_target | 0.9 | Доля времени до следующего checkpoint’а, за которую нужно завершить сброс (например, 4.5 мин из 5) |
checkpoint_flush_after | 256kB | Принудительный fsync после записи такого объёма (для SSD/NVMe) |
Пример: что происходит при сбое?
- Сервер упал в 10:03.
- Последний checkpoint был в 10:00 (LSN =
0/1A000000). - При перезапуске:
- PostgreSQL читает
pg_control→ видит LSN0/1A000000, - Начинает проигрывать WAL с этого LSN,
- Применяет все изменения до момента сбоя → база восстановлена.
- PostgreSQL читает
Без checkpoint’а пришлось бы проигрывать весь WAL с самого начала — что нереально.
fsync — это системный вызов операционной системы, который гарантирует, что все данные, записанные в буферы ядра ОС для конкретного файла, физически сохранены на постоянное хранилище (HDD, SSD и т.д.).
Зачем это нужно в PostgreSQL?
«Изменения в данных можно применять на диск только после того, как соответствующая запись WAL уже надёжно сохранена на диск».
А «надёжно сохранена» означает: вызван fsync для файла WAL, и ОС подтвердила, что данные фактически записаны на носитель, а не просто лежат в кэше оперативной памяти или кэше диска.