Получить доступ

Что такое журнал предзаписи (WAL) и зачем он нужен?

MiddleХранение данных
Ещё спрашивают так:
  • Как база данных переживает внезапное отключение питания?
  • Что такое write-ahead log?
  • Как работает репликация через журнал?
Коротко

Сначала запись в журнал, потом в данные. Перед изменением страниц база дописывает в конец журнала, что собирается изменить, и делает fsync. После сбоя журнал проигрывается заново — подтверждённые транзакции восстанавливаются.

  • Последовательная запись журнала дешевле случайной записи страниц
  • Страницы данных пишутся на диск позже, пачками — на контрольной точке (checkpoint)
  • Коммит = журнал на диске; отсюда цена fsync и group commit

А ещё Тот же журнал — основа репликации, point-in-time recovery и CDC (Debezium)

Так подсказку видит пользователь sotto на живом собеседовании — за пару секунд, пока вы думаете вслух.

Подробно

Проблема. Транзакция меняет несколько страниц в разных местах файла. Если записывать их сразу и питание пропадёт посередине, на диске окажется половина изменений — нарушится атомарность. А если ждать записи всех страниц при каждом коммите — это много случайных fsync.

Решение — журнал предзаписи:

  1. изменение сначала описывается записью в журнале (что, где, новое значение) — последовательное дописывание в конец файла;
  2. при коммите журнал сбрасывается на диск (fsync) до записи подтверждения клиенту — это и есть durability из ACID;
  3. изменённые страницы остаются в памяти (буферный кэш) и пишутся на диск позже, в фоне;
  4. периодически выполняется контрольная точка: все грязные страницы сбрасываются, и журнал до этого места больше не нужен для восстановления.

Восстановление после сбоя: с последней контрольной точки журнал читается и изменения повторяются (redo). Транзакции без записи о коммите отбрасываются (в PostgreSQL их версии строк просто невидимы благодаря MVCC; в других СУБД есть ещё undo-журнал для отката).

Почему это быстрее: запись в конец файла последовательная, а несколько коммитов можно сбросить одним fsync (group commit). Сами страницы данных пишутся реже и пачками.

Журнал как поток изменений:

  • репликация — реплика получает журнал и применяет его (физическая потоковая репликация PostgreSQL, binlog в MySQL);
  • восстановление на момент времени — базовая копия плюс архив журнала до нужной секунды;
  • CDC — логическое декодирование журнала публикует изменения в Kafka (Debezium) без двойной записи из приложения.

Настройки компромисса: synchronous_commit = off в PostgreSQL не ждёт fsync при коммите — быстрее, но при падении можно потерять последние доли секунды транзакций (без порчи данных). innodb_flush_log_at_trx_commit в MySQL — то же самое.

Идея журнала повсюду: файловые системы с журналированием (ext4), Kafka (вся система — журнал), LSM-хранилища, Raft (реплицированный журнал).

Пример

LSN 0/16B3F20  BEGIN xid=812
LSN 0/16B3F58  UPDATE accounts page=17 slot=4  balance: 500 → 300
LSN 0/16B3FA0  UPDATE accounts page=93 slot=1  balance: 100 → 300
LSN 0/16B3FE8  COMMIT xid=812     ← fsync до этой записи, затем «OK» клиенту
...                               ← страницы 17 и 93 запишутся на checkpoint

Что хотят услышать

  • Правило: журнал на диск раньше данных.
  • Как это даёт атомарность и долговечность после сбоя.
  • Почему быстрее: последовательная запись, group commit, отложенная запись страниц.
  • Контрольные точки и восстановление.
  • Журнал как основа репликации и CDC — плюс.

Частые ошибки

  • Думать, что при коммите база синхронно пишет все изменённые страницы.
  • Путать WAL с логами приложения.

Что спросят дальше

Связанные вопросы

Закрытая бета

Подсказки на собеседовании — в реальном времени

sotto слышит вопрос интервьюера и показывает короткий ответ и план, как в блоке «Коротко». Оставьте контакт — пришлём доступ и промокод.

  • Промокод на 2 часа — сверх пробных 30 минут
  • Программа для Windows — скачать сразу, войти — через Яндекс ID или VK ID
  • Прямая связь с разработчиком: что улучшить — сделаем