Ответ
Лог предзаписи (Write-Ahead Log, WAL) — это стандартный механизм обеспечения атомарности и долговечности (две из четырех гарантий ACID) в системах управления базами данных.
Принцип работы:
Перед тем как изменить данные в основных файлах БД на диске, все операции изменения сначала последовательно дописываются в специальный файл — лог (WAL-файл). И только после успешной записи в лог транзакция считается зафиксированной (committed
).
Пошаговый процесс:
- Начало транзакции.
- Запись в лог: Все изменения (например,
INSERT
,UPDATE
,DELETE
) записываются в конец WAL-файла. - Подтверждение: Как только запись в лог успешно завершена, система может подтвердить клиенту успешное выполнение транзакции.
- Применение изменений (Checkpointing): Позже, в фоновом режиме или в определенные моменты, эти изменения из лога переносятся в основные файлы данных.
Основные преимущества:
- Надежность (Durability): Если система выйдет из строя до того, как изменения будут записаны в основные файлы, после перезапуска СУБД сможет восстановить свое состояние, "проиграв" записи из WAL.
- Производительность: Последовательная запись в один файл (лог) значительно быстрее, чем множество случайных записей в разные места на диске (основные файлы данных).
Примеры систем, использующих WAL: PostgreSQL, SQLite, Oracle, LevelDB.
В Go, встраиваемые key-value хранилища, такие как bbolt
(форк BoltDB), используют этот механизм. Хотя вы не взаимодействуете с WAL напрямую, каждая транзакция db.Update
полагается на него для обеспечения безопасности данных:
// Этот код использует bbolt, который под капотом реализует WAL
db, err := bbolt.Open("my.db", 0600, nil)
if err != nil {
log.Fatal(err)
}
defer db.Close()
// Эта транзакция будет сначала записана в WAL, а затем применена
err = db.Update(func(tx *bbolt.Tx) error {
b, err := tx.CreateBucketIfNotExists([]byte("MyBucket"))
if err != nil {
return err
}
return b.Put([]byte("key"), []byte("value"))
})