Что такое WAL (Write-Ahead Log) и как он используется для восстановления БД после сбоев?

Ответ

Write-Ahead Log (WAL) — это стандартный механизм для обеспечения атомарности и долговечности (буквы 'A' и 'D' в ACID) в базах данных. Его суть в том, что все изменения сначала записываются в специальный журнал (лог-файл) и только после этого — в основные файлы данных.

Как WAL работает при восстановлении после сбоя:

Когда база данных запускается после сбоя (например, отключения питания), она выполняет процедуру восстановления, используя WAL:

  1. Накатывание (Redo): БД просматривает WAL с последней контрольной точки (checkpoint) и применяет все зафиксированные (committed) транзакции, которые могли не успеть записаться в основные файлы данных. Это обеспечивает долговечность.

  2. Откат (Undo/Rollback): После этого БД ищет в логе транзакции, которые были начаты, но не имеют записи о COMMIT. Все изменения, сделанные этими незавершенными транзакциями, отменяются. Это обеспечивает атомарность.

Пример сценария:

Представим транзакцию перевода денег:

BEGIN;
-- 1. Запись в WAL: списать 100 у id=1
UPDATE accounts SET balance = balance - 100 WHERE id = 1;

-- 2. Запись в WAL: начислить 100 id=2
UPDATE accounts SET balance = balance + 100 WHERE id = 2;

-- !!! В ЭТОТ МОМЕНТ ПРОИСХОДИТ СБОЙ ПИТАНИЯ !!!

COMMIT; -- Эта запись не попадает в WAL

При восстановлении:

  • База данных увидит в WAL записи об UPDATE для этой транзакции.
  • Однако она не найдет запись о COMMIT.
  • Система сделает вывод, что транзакция не была завершена, и откатит оба изменения (UPDATE). Баланс счетов останется в исходном, согласованном состоянии.

Ответ 18+ 🔞

Вот, смотри, объясняю как есть, без этих ваших заумных букв. WAL — это, блядь, такой журнал предзаписи, который база данных ведёт, чтобы не обосраться при сбое. Суть проще пареной репы: прежде чем что-то ткнуть в основную таблицу, база всё аккуратненько записывает в отдельный лог-файлик. Как будто черновик перед чистовиком, только наоборот — сначала черновик, а потом уже по нему переписывают.

Как эта штука вытаскивает базу из жопы после того, как всё накрылось медным тазом (например, свет вырубили):

База просыпается, моргает, и первым делом лезет в этот самый WAL.

  1. Накат (Redo): Она тупо проматывает лог с последней контрольной точки и повторяет всё, что там было зафиксировано, но могло не долететь до основных данных. Это чтобы твои сохранённые деньги не сгорели. Обеспечивает, блядь, долговечность — то, что ты записал, уже никуда не денется.
  2. Откат (Undo): А потом она ищет в этом журнале дела, которые начались, но так и не кончились как положено — без записи COMMIT. И всё, что натворили эти полупидоры-транзакции, она откатывает к ебеням. Это чтобы атомарность была — либо всё сделалось, либо нихуя.

Пример, чтобы вообще мозг не взорвался:

Допустим, перевод денег:

BEGIN;
-- 1. В WAL пишется: спиздить 100 у id=1
UPDATE accounts SET balance = balance - 100 WHERE id = 1;

-- 2. В WAL пишется: прибавить 100 id=2
UPDATE accounts SET balance = balance + 100 WHERE id = 2;

-- !!! И В ЭТОТ САМЫЙ МОМЕНТ ХУЯК — БЛЯДЬ, БЕЗ СВЕТА ОСТАЛИСЬ !!!

COMMIT; -- Эту бумажку в журнал уже не успели сунуть.

Что будет, когда база очухается:

Она откроет WAL, увидит там две записи об обновлениях, но, ёпта, не найдёт рядом с ними жирной печати COMMIT. И сделает единственно верный вывод: «А, ну это, значит, мудак какой-то начал дело и бросил на полпути, пидарас шерстяной».

И откатит оба этих UPDATE нахуй. Деньги вернутся на исходные места, и в итоге всё будет чисто, как будто ничего и не было. Вот так вот, в рот меня чих-пых, эта хитрая жопа под названием WAL и работает.