Что такое журнал предзаписи (WAL) и зачем он нужен?
- Как база данных переживает внезапное отключение питания?
- Что такое write-ahead log?
- Как работает репликация через журнал?
Сначала запись в журнал, потом в данные. Перед изменением страниц база дописывает в конец журнала, что собирается изменить, и делает fsync. После сбоя журнал проигрывается заново — подтверждённые транзакции восстанавливаются.
- Последовательная запись журнала дешевле случайной записи страниц
- Страницы данных пишутся на диск позже, пачками — на контрольной точке (checkpoint)
- Коммит = журнал на диске; отсюда цена fsync и group commit
А ещё Тот же журнал — основа репликации, point-in-time recovery и CDC (Debezium)
Подробно
Проблема. Транзакция меняет несколько страниц в разных местах файла. Если записывать их сразу и питание пропадёт посередине, на диске окажется половина изменений — нарушится атомарность. А если ждать записи всех страниц при каждом коммите — это много случайных fsync.
Решение — журнал предзаписи:
- изменение сначала описывается записью в журнале (что, где, новое значение) — последовательное дописывание в конец файла;
- при коммите журнал сбрасывается на диск (fsync) до записи подтверждения клиенту — это и есть durability из ACID;
- изменённые страницы остаются в памяти (буферный кэш) и пишутся на диск позже, в фоне;
- периодически выполняется контрольная точка: все грязные страницы сбрасываются, и журнал до этого места больше не нужен для восстановления.
Восстановление после сбоя: с последней контрольной точки журнал читается и изменения повторяются (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 с логами приложения.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Сначала изменяются страницы данных, а потом в журнал пишется отчёт об изменениях — он нужен только для репликации на другие серверы
- ✓Сначала изменение пишется в журнал с fsync, потом в страницы данных; после сбоя журнал проигрывается
- ✗WAL нужен только для репликации
- ✗Запись журнала дороже, чем случайная запись страниц
Что спросят дальше
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.