InnoDB змінює сторінки даних у буферному пулі, а на диск скидає їх пізніше. Щоб закомічені зміни не пропали при збої, працює журнал повтору (redo log): перед комітом опис змін послідовно записується в журнал. Послідовний запис невеликих записів значно дешевший за запис випадкових сторінок по 16 КБ.
Відновлення після збою: під час старту InnoDB читає журнал від останньої контрольної точки й повторно застосовує зміни, що не встигли потрапити у файли даних. Незакомічені транзакції відкочуються за undo-журналом.
innodb_flush_log_at_trx_commit визначає, що відбувається під час COMMIT:
| Значення | Що робиться | Що можна втратити |
|---|---|---|
1 (за замовчуванням) |
запис у журнал і fsync на кожен коміт |
нічого (повна ACID-стійкість) |
2 |
запис в ОС на коміт, fsync раз на секунду |
~1 с транзакцій при падінні ОС чи живлення; падіння лише mysqld не страшне |
0 |
запис і fsync раз на секунду |
~1 с транзакцій навіть при падінні mysqld |
fsync - найдорожча частина коміту, тож 2 і 0 дають помітний виграш на дрібних транзакціях. Але це свідома відмова від стійкості. Прийнятно для реплік, що легко перестворити, чи для тимчасового масового імпорту - не для основної бази з грошима.
Друга половина стійкості - sync_binlog (за замовчуванням 1): fsync бінарного журналу на кожен коміт. Без нього після збою репліки можуть отримати транзакції, яких немає на джерелі, чи навпаки.
Подвійний запис (doublewrite buffer) захищає від «розірваних» сторінок: якщо живлення зникло посеред запису 16-КБ сторінки, на диску лишиться напівзаписана сторінка, яку журнал повтору не виправить. Тому InnoDB спершу пише сторінки в окрему область doublewrite, а потім на місце. Після збою пошкоджена сторінка відновлюється з копії.
Розмір журналу повтору (innodb_redo_log_capacity з MySQL 8.0.30, за замовчуванням 100 МБ). Замалий журнал змушує часто робити контрольні точки й агресивно скидати сторінки - запис стає ривками. Завеликий подовжує відновлення після збою. Орієнтир - щоб журнал вміщав щонайменше годину запису під піковим навантаженням.
Що варто знати: групування комітів (group commit) дає змогу кільком транзакціям поділити один fsync, тож налаштування 1 під паралельним навантаженням коштує менше, ніж здається на синтетичному тесті з одним клієнтом.