MariaDB проти SQLite: просте відновлення чи справжній PITR

Було корисно?

Найшвидший спосіб зіпсувати спокійний вівторок — виявити, що ваш «бекап» насправді лише файл, який хтось одного разу скопіював,
під час роботи процесу, що записував у цей файл, і ніхто ніколи не практикував відновлення. Другий за швидкістю спосіб —
усвідомити, що вам потрібне відновлення до певного моменту (PITR), але ви ніколи не зберігали журнали, які роблять PITR можливим.

SQLite і MariaDB знаходяться на протилежних кінцях операційного спектру. SQLite — це файл. MariaDB — це сервер з рухомими частинами,
журналом попереднього запису, реплікацією і здатністю «відмотати час», якщо ви налаштуєте це.
Це практичний посібник по резервним копіям, які реально відновлюються, а не по тим, що заспокоюють.

Що ви насправді купуєте: «відновлення» проти «PITR»

«Резервна копія» — перевантажений термін. У більшості організацій це означає «у нас десь є якісь байти». У продакшні це означає:
ми можемо відновити сервіс і дані до прийнятної точки, у прийнятний час, з передбачуваним ризиком.
Це і є RPO (скільки даних ви можете втратити) та RTO (як довго ви можете бути недоступні) простими словами.

Суперсила SQLite — простота: одна база даних — один файл. Якщо ви вмієте зробити консистентну копію та зберігати версії,
ви можете швидко відновитися. Але PITR не є рідною, першокласною можливістю. Його можна наближати частими снапшотами,
архівацією WAL або журналом на рівні застосунку, але це не те саме, що відтворення журналу транзакцій до конкретної секунди.

Суперсила MariaDB — саме журнал транзакцій: бінарні журнали (binlog). Якщо ви зберігаєте консистентну базову резервну копію і
утримуєте binlog-и, ви можете відновити «безпосередньо перед тим, як хтось видалив таблицю» або «перед релізом багу» в межах
точності подій і позицій у журналі. Це більше операційної роботи, більше дискового простору, більше режимів відмов — і значно краща відповідь,
коли бізнес запитує: «Чи можемо ми повернутися до стану на 10:41?»

Просте відновлення (добре, коли…)

  • Ви можете терпіти втрату останніх N годин записів (RPO у годинах, а не в хвилинах).
  • Обсяги записів низькі, і БД не є джерелом істини для системи.
  • Вартість налаштування та експлуатації PITR перевищує витрати від випадкових втрат.
  • Ваша головна загроза — відмова інфраструктури, а не помилкові дії користувача чи погані деплоя.

Справжній PITR (неприпустимо, коли…)

  • Наявні реальні загрози: випадкові видалення, невдалi міграції або баги в додатку.
  • Потрібно відновити «до часу», а не тільки «до дня».
  • Потрібне відновлення рівня аудиту: пояснюване, відтворюване і тестоване.
  • Регульовані дані або контрактні SLA роблять «втрату півдня» неприйнятною.

Сухий факт: резервні копії — це функція надійності. Ставтеся до них як до будь-якої іншої продакшн‑фічі — проектуйте, експлуатуйте, тестуйте і вимірюйте.
«Фіча» — не сама задача бекапу; фіча — це результат відновлення.

Перефразована ідея від Werner Vogels (reliability/operations): «Все ламається постійно; проектуйте, припускаючи відмову.»
Ваші резервні копії — це частина, де ви погоджуєтеся, що він правий.

Цікаві факти та історичний контекст (чому налаштування за замовчуванням виглядають дивно)

  1. SQLite була створена у 2000 році Д. Річардом Гіппом для вбудованого використання — мала, портативна, без адміністрування.
    Це не «малий MySQL». Це бібліотека з власним форматом файлу.
  2. Модель одного автора у SQLite (з багатьма читачами) — свідомий дизайн, щоб тримати блокування простим.
    Режим WAL покращує конкурентність, але не перетворює SQLite на сервер.
  3. Концепція «гарячого бекапу» в SQLite існує тому, що копіювання живого файлу бази може бути неконсистентним.
    Безпечний шлях резервного копіювання — це першокласний API і CLI‑функція.
  4. MariaDB відгалузилася від MySQL після придбання Sun корпорацією Oracle у 2010 році; багато операційних поведінок (binlogs, InnoDB)
    залишилися сумісними по суті, хоча функції розходяться.
  5. Binlog-і MySQL/MariaDB створювалися для реплікації і пізніше стали основою PITR у багатьох компаніях.
    PITR — щасливий наслідок «нам потрібно відправляти зміни кудись ще».
  6. Відновлення після збоїв InnoDB (redo‑логи) — не те саме, що PITR. Redo‑логи допомагають відновити консистентний стан після крашу,
    але не до обраного моменту перед поганим запитом.
  7. Логічні дампи (mysqldump) колись були стандартним підходом, бо вони портативні і прості, але повільні на великих даних,
    а відновлення часто займає ще більше часу.
  8. Percona XtraBackup популяризував «гарячі фізичні бекапи» для InnoDB шляхом копіювання сторінок і застосування логів; у MariaDB є власне
    екосистема інструментів і сумісності, але операційна ідея та ж.

Резервні копії SQLite: правильне відновлення файлів

Стратегія резервних копій SQLite здебільшого про чесність із собою щодо «просто скопіюйте файл».
Якщо процес записує під час копіювання, файл може не відповідати валідному консистентному стану.
Інколи пощастить. Продакшн — це місце, де удача помирає.

Три реалії SQLite, які варто прийняти одразу

  • Резервні копії або консистентні, або театр. Бітова ідентична копія, зроблена у невірний момент, усе ще марна.
  • WAL змінює історію бекапів. Якщо ви працюєте в режимі WAL, стан БД розподілений між основним файлом і WAL‑файлом.
    Резервне копіювання одного без іншого — класична пастка «все працювало у стенді».
  • PITR — це не просто галочка. Ви можете наближати PITR частими снапшотами (файлова система/ZFS/LVM),
    архівацією WAL або журналом подій на рівні застосунку. Але якщо питання — «відновити на 10:41:17», життя ускладнюється.

Як виглядає «добре» для резервних копій SQLite

Для більшості вбудованих розгортань «добре» означає:

  • Використовуйте режим WAL, якщо потрібна конкурентність, але створюйте його коректно.
  • Використовуйте онлайн‑механізм резервного копіювання SQLite (VACUUM INTO або .backup) для консистентних копій.
  • Версіонуйте бекапи (з іменами з часовими мітками або ID снапшотів).
  • Запускайте перевірки цілісності на відновлених копіях, а не на живій БД під навантаженням.

Опції «на кшталт PITR» для SQLite (виберіть одну й будьте чесними щодо недоліків)

SQLite не постачає binlog, який можна відтворити до довільного часу. Ось практичні наближення:

  • Часті снапшоти файлів БД. Добре працює з ZFS/btrfs/LVM снапшотами. Ваша «роздільна здатність PITR» — частота снапшотів.
  • Архівування файлів WAL. Це дає більш тонке відновлення, але потребує дисциплінованої схеми і ретельної процедури відновлення.
    Багато команд зупиняються на цьому і все одно не можуть коректно відтворити, бо не зафіксували межі чекпоінтів або неправильно обертають WAL.
  • Журнал подій на рівні застосунку. Якщо БД — кеш або локальне сховище, можливо, ви можете відновити з upstream‑подій.
    Це не PITR; це реконструкція. І може бути кращим — якщо upstream заслуговує на довіру.

Жарт №1: резервні копії SQLite як кімнатні рослини — проігноруєш їх місяць, і раптом о 2 ранку гуглиш «чому це стало коричневим».

Резервні копії MariaDB: повні, інкрементні та PITR на основі binlog

Дизайн бекапів MariaDB — це трикомпонентна система: консистентна базова копія, ретеншн binlog‑ів
та відпрацьована процедура відновлення. Пропустіть будь‑який з цих кроків — і ваш «PITR» перетвориться на презентацію.

Базові резервні копії: логічні проти фізичних

Інтернет любить сперечатися тут. У продакшні обирайте, виходячи з розміру даних, часу відновлення та операційних обмежень.

  • Логічний бекап (mariadb-dump / mysqldump): Портативний і простий. Повільніший, більший, а відновлення часто болісно повільне.
    Підходить для невеликих наборів даних, міграцій схем або коли потрібен читаємий людині дамп.
  • Фізичний бекап (mariabackup / xtrabackup‑подібні): Швидший для великих наборів, і відновлення може бути значно швидшим.
    Потребує сумісності движка/файлового розміщення та ретельнішого опрацювання, але це серйозний вибір для великих обсягів.

Binlog-и: різниця між «відновленням» і «відмотуванням»

Binlog-и записують зміни. Якщо ви їх зберігаєте, ви можете відтворити вперед від базової копії до обраного моменту.
Якщо не зберігаєте — не можете. Ніяких хитрощів, лише торги.

PITR з MariaDB зазвичай виглядає так:

  1. Відновити базову копію на новому сервері або в ізольованому інстансі.
  2. Застосувати binlog-и до часу зупинки (або до позиції) безпосередньо перед інцидентом.
  3. Перевірити консистентність даних і поведінку застосунку.
  4. Перенаправити трафік або експортувати виправлені дані назад у продакшн.

Реплікація — це не резервна копія (але може бути частиною плану)

Реплікація копіює помилки зі швидкістю світла. Це її завдання. Репліка може допомогти, якщо:

  • Ви використовуєте затриману реплікацію (навмисний лаг) і помічаєте інцидент до закінчення вікна.
  • Ви можете швидко зупинити SQL‑потік і трактувати репліку як «тайм‑капсулу».
  • У вас все ще є binlog-и для відтворення або для побудови чистого клону.

Жарт №2: реплікація — це не резервна копія — це груповий чат, де всі миттєво повторюють неправильну відповідь.

Реалії «справжнього PITR» (і що це коштує)

PITR — це не «увімкнути binlog». Це операційний контракт:

  • Зберігання: достатньо binlog‑ів, щоб покрити вікно відновлення (плюс запас).
  • Частота базових бекапів: достатньо часта, щоб час відтворення був прийнятним.
  • Синхронізація часу: узгоджені системні годинники, відомі часові пояси та обережна інтерпретація часових міток.
  • Практика відновлення: як мінімум щомісячні або щоквартальні тренування з задокументованими часами і записами про помилки.

Найбільша прихована вартість — людська: вперше, коли ви робите відтворення binlog під тиском, ви виявите неправильні припущення.
Якщо пощастить, ви виявите їх під час тренування.

Практичні завдання: команди, виводи та рішення (12+)

Це ті завдання, які я фактично виконую (або прошу виконати), коли оцінюю позицію резервного копіювання або виконую відновлення.
Кожне містить: команду, приклад виводу, що це означає, і яке рішення прийняти.

Завдання 1 — SQLite: визначити режим журналу (WAL змінює все)

cr0x@server:~$ sqlite3 /var/lib/app/app.db 'PRAGMA journal_mode;'
wal

Значення: увімкнено режим WAL. Записи йдуть у app.db-wal, а чекпоінти зливають їх у основний файл БД.

Рішення: потрібно використовувати метод гарячого бекапу або знімати стан DB і WAL атомарно. «cp app.db» неприйнятно.

Завдання 2 — SQLite: зробити консистентний онлайн‑бекап за допомогою .backup

cr0x@server:~$ sqlite3 /var/lib/app/app.db ".backup '/backups/app.db.2025-12-30T0200Z'"

Значення: SQLite використовує API бекапу, щоб зробити консистентну копію навіть під час використання БД.

Рішення: надавайте перевагу цьому способу над копією файлової системи, коли дозволяє I/O. Якщо це занадто повільно — переходьте на снапшот‑підхід.

Завдання 3 — SQLite: використати VACUUM INTO для компактної, консистентної копії

cr0x@server:~$ sqlite3 /var/lib/app/app.db "VACUUM INTO '/backups/app.compact.db';"

Значення: створює новий файл бази, дефрагментований і консистентний. Часто менший, інколи значно менший.

Рішення: використовуйте для нічних бекапів, коли важливий розмір. Уникайте в пікове навантаження: це I/O‑інтенсивна операція.

Завдання 4 — SQLite: перевірка цілісності відновленої копії (не на живій БД)

cr0x@server:~$ sqlite3 /backups/app.db.2025-12-30T0200Z "PRAGMA integrity_check;"
ok

Значення: внутрішні перевірки консистентності пройшли.

Рішення: вважайте це проходом‑воротами. Якщо результат не «ok», ваш пайплайн бекапів зламаний, поки не виправите.

Завдання 5 — SQLite: перевірити наявність WAL‑файлів та їх розмір (індикатор ризику резервного копіювання)

cr0x@server:~$ ls -lh /var/lib/app/app.db*
-rw-r----- 1 app app 1.2G Dec 30 01:59 /var/lib/app/app.db
-rw-r----- 1 app app 512M Dec 30 02:00 /var/lib/app/app.db-wal
-rw-r----- 1 app app  32K Dec 30 01:58 /var/lib/app/app.db-shm

Значення: WAL великий. Чекпоінт може відставати; копії, що ігнорують WAL, не міститимуть останніх транзакцій.

Рішення: розслідувати чекпоінтинг і метод бекапу. Розгляньте примусовий чекпоінт у контрольоване вікно або налаштуйте параметри WAL.

Завдання 6 — MariaDB: підтвердити, що увімкнено binlogging

cr0x@server:~$ mariadb -e "SHOW VARIABLES LIKE 'log_bin';"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin       | ON    |
+---------------+-------+

Значення: сервер генерує binlog-и.

Рішення: якщо OFF, припиніть вдавати, що у вас є PITR. Увімкніть, сплануйте рестарт, якщо потрібно, і відразу запроєктуйте ретеншн.

Завдання 7 — MariaDB: перевірити формат binlog (row‑based — ваш друг)

cr0x@server:~$ mariadb -e "SHOW VARIABLES LIKE 'binlog_format';"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW   |
+---------------+-------+

Значення: журнал у форматі рядків записує зміни рядків, загалом безпечніший для PITR і коректності реплікації.

Рішення: надавайте перевагу ROW для PITR. Якщо у вас STATEMENT, будьте готові до недетермінованості через функції та тригери.

Завдання 8 — MariaDB: підтвердити налаштування збереження binlog

cr0x@server:~$ mariadb -e "SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';"
+--------------------------+--------+
| Variable_name            | Value  |
+--------------------------+--------+
| binlog_expire_logs_seconds | 604800 |
+--------------------------+--------+

Значення: binlog-и видаляються через 7 днів (604800 секунд).

Рішення: узгодьте ретеншн із потрібним вікном відновлення плюс час на виявлення. Якщо інциденти помічають через два тижні, 7 днів — фантазія.

Завдання 9 — MariaDB: перелік доступних binlog‑ів (чи є історія?)

cr0x@server:~$ mariadb -e "SHOW BINARY LOGS;"
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mariadb-bin.000231 | 104857600 |
| mariadb-bin.000232 | 104857600 |
| mariadb-bin.000233 |  52428800 |
+------------------+-----------+

Значення: binlog‑файли існують і розміри виглядають правдоподібними.

Рішення: якщо список короткий або порожній — діапазон PITR короткий або відсутній. Виправте ретеншн і стратегію архівації.

Завдання 10 — MariaDB: зробити логічну базову резервну копію (невеликі набори / портативність)

cr0x@server:~$ mariadb-dump --single-transaction --routines --triggers --events --all-databases > /backups/mariadb.full.sql

Значення: консистентний знімок для InnoDB через --single-transaction. Включає процедури/тригери/події.

Рішення: використовуйте, якщо набір даних невеликий і час відновлення прийнятний. Якщо відновлення займає години і ваш RTO — хвилини, переходьте на фізичні бекапи.

Завдання 11 — MariaDB: зробити фізичний базовий бекап за допомогою mariabackup

cr0x@server:~$ mariabackup --backup --target-dir=/backups/mariadb/base --user=backup --password='REDACTED'
[00] 2025-12-30 02:05:12 completed OK!

Значення: файли скопійовані з необхідними метаданими для застосування логів.

Рішення: якщо це періодично падає — підозрюйте проблеми з дозволами, I/O‑переповнення або недостатньо тимчасового простору. Виправте це до того, як обіцяти PITR.

Завдання 12 — MariaDB: підготувати (застосувати логи) перед відновленням

cr0x@server:~$ mariabackup --prepare --target-dir=/backups/mariadb/base
[00] 2025-12-30 02:08:44 InnoDB: Shutdown completed; log sequence number 987654321

Значення: бекап приведено до консистентного стану; redo застосовано.

Рішення: бекап, який не був підготовлений, не готовий до відновлення. Зробіть «prepare succeeded» частиною пайплайну.

Завдання 13 — MariaDB: захопити координати binlog під час бекапу

cr0x@server:~$ mariadb -e "SHOW MASTER STATUS\G"
*************************** 1. row ***************************
             File: mariadb-bin.000233
         Position: 184467
     Binlog_Do_DB:
 Binlog_Ignore_DB:

Значення: це файл і позиція binlog, що відповідають точці консистентності вашого знімка (для багатьох методів бекапу).

Рішення: зберігайте це разом з метаданими базової копії. Без координат відтворення binlog‑ів стає археологією.

Завдання 14 — MariaDB: сухий прогін перегляду binlog навколо часу інциденту

cr0x@server:~$ mysqlbinlog --start-datetime="2025-12-30 10:35:00" --stop-datetime="2025-12-30 10:45:00" /var/lib/mysql/mariadb-bin.000233 | head
# at 184467
#251230 10:36:01 server id 1  end_log_pos 184742 CRC32 0x9a3c1f2e  GTID 0-1-12345  trans
BEGIN
# at 184742
#251230 10:36:01 server id 1  end_log_pos 185120 CRC32 0x0e1d2b44  Table_map: `prod`.`orders` mapped to number 241

Значення: видно межі транзакцій і таймінг подій.

Рішення: ідентифікуйте вікно «поганої» транзакції. Вирішіть, чи будете зупинятися по datetime чи по позиції/GTID для точності.

Завдання 15 — MariaDB: відтворити binlog-и до часу зупинки (виконання PITR)

cr0x@server:~$ mysqlbinlog --stop-datetime="2025-12-30 10:41:00" /backups/binlogs/mariadb-bin.000233 /backups/binlogs/mariadb-bin.000234 | mariadb

Значення: відтворює зміни в відновлений інстанс до часу зупинки.

Рішення: якщо бачите помилки — зупиніть процес. Переконайтеся, що застосовуєте на правильну базову копію і що GTID/IDs серверів співпадають.

Завдання 16 — MariaDB: перевірити replication/GTID режим перед довірою GTID‑відновленню

cr0x@server:~$ mariadb -e "SHOW VARIABLES LIKE 'gtid_strict_mode';"
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| gtid_strict_mode | ON    |
+------------------+-------+

Значення: увімкнена суворість GTID; позиціонування по GTID, ймовірно, надійне.

Рішення: якщо GTID різняться між середовищами, надавайте перевагу file+position і тримайте середовище відновлення ізольованим.

Завдання 17 — Саніті: виміряти пропускну здатність відновлення і вирішити, чи треба змінити частоту базових бекапів

cr0x@server:~$ /usr/bin/time -f "elapsed=%E cpu=%P" mariadb < /backups/mariadb.full.sql
elapsed=01:42:18 cpu=86%

Значення: логічне відновлення зайняло ≈1год42хв на цьому обладнанні.

Рішення: якщо ваш RTO — 30 хвилин, потрібні фізичні відновлення, швидші хости відновлення, або інша архітектура. З фізикою не домовляються.

Швидкий план діагностики (знайдіть вузьке місце швидко)

Коли бекапи або відновлення повільні чи падають, не вгадуйте. Перевірте нудні обмеження спочатку. Зазвичай вони винні.

По‑перше: накопичувачі та насичення I/O

  • Перевірте вільне місце на диску (ціль для бекапів і джерело). Помилки out‑of‑space часто проявляються як «корупція» пізніше.
  • Перевірте I/O wait. «Повільний інструмент бекапу» часто означає насичений том.
  • Перевірте спалахи затримки файлової системи. Снапшоти або роботи з компактування можуть зруйнувати вікна бекапу.

По‑друге: механіка консистентності

  • SQLite: ви бекапите через API або сліпо копіюєте файли? Чи захоплюєте WAL/shm правильно?
  • MariaDB: використовуєте --single-transaction для логічних дампів? Підготовлено фізичний бекап?
  • Binlog-и: чи маєте ви правильні координати binlog? Чи ще збережені потрібні файли binlog?

По‑третє: операційна інфраструктура

  • Права доступу та профілі SELinux/AppArmor.
  • Плутанина з часом/часовим поясом (stop‑datetime, застосований у неправильному часовому поясі — класика).
  • Мережеві вузькі місця до об’єктного сховища або NFS.
  • ЦП‑насичення при стисненні (особливо якщо ви «оптимізували» це).

Три корпоративні міні‑історії з поля бою резервних копій

Міні‑історія 1: інцидент через хибне припущення

Середня компанія запускала продукт підтримки клієнтів, що зберігав стан черги у SQLite на кожному вузлі додатку.
Це не було джерелом істини — поки раптово ним не стало. Нова фіча почала записувати «кінцеві» результати локально,
щоб пришвидшити завантаження сторінок. Ніхто не оновив класифікацію даних. Таке трапляється.

Бекапи були cron‑скриптом: cp app.db /mnt/backups/app.db. Здавалося, все гаразд. Відновлення працювало в песочниці,
бо навантаження там було низьким і чекпоінти були частими.

Потім інцидент: вузол перезавантажився під час піку. Після старту додаток падав при читанні деяких рядків.
Команда спробувала відновитися з копії файлу. Та сама помилка. Спробували старіші копії — деякі працювали, деякі ні.
Бекапи були рулеткою.

Корінна причина була проста: режим WAL було увімкнено місяці тому для зменшення блокувань записувача, але «бекап» копіював лише основний файл.
Іноді WAL мав критичні транзакції, що ще не були чекпоінтовані. Копія файлу без WAL була неконсистентною щодо очікувань застосунку.

Виправлення було також просте й трохи принизливе: замінити cp на API бекапу SQLite і додати крок перевірки цілісності на артефакті.
Також задокументували наявність WAL і що це не опція. Інцидент був не стільки про SQLite, скільки про припущення, що копія файлу = бекап БД.

Міні‑історія 2: оптимізація, що повернулася бумерангом

Інша організація працювала на MariaDB для бізнес‑платформи. Бекапи були фізичні і надійні, але вікно бекапу почало заходити в бізнес‑години.
Хтось вирішив сильніше стиснути бекапи, щоб зменшити обсяг і пришвидшити завантаження у віддалене сховище.

Стиснення дійсно зменшило байти на диску. Але воно також завантажило CPU на години і збільшило I/O wait, бо конвеєр перестав бути «швидкість копіювання» і став «швидкість CPU».
Сервер БД почав показувати стрибки затримок під час бекапів, і команда застосунку звинуватила «MariaDB знову повільна».

Вони відреагували, знижуючи тиск InnoDB buffer pool і налаштовуючи кеші запитів (так, справді). Затримки стали ще гіршими.
Справжня проблема була в тому, що процес бекапу конкурував з продуктивним трафіком за CPU‑цикли та кеш.

Негативний ефект проявився під час drill‑відновлення. Розпакування стало довготерміновою операцією. Теоретична економія пропускної здатності не важила,
бо RTO визначався часом розпаковування, прив’язаним до CPU. Відновлення не відповідало внутрішнім цілям.

Постмортем був непривабливий: використовувати легше стиснення або його відмовитись для «гарячого» шляху відновлення, важке стиснення — лише для холодного архіву,
і виконувати бекапи на репліці або виділеному хості для бекапів, коли це можливо. Зберігання дешевше за простій; CFO не хоче дзвінків о 3 ранку.

Міні‑історія 3: нудна, але правильна практика, що врятувала день

Команда фінансових послуг працювала на MariaDB зі строгим контролем змін. Вони робили одну річ, що здавалася майже ностальгічною:
щомісяця вони виконували повне відновлення в ізольованому середовищі, а потім запускали набір відомих запитів для валідації сум по бізнесу.
Це було не весело. Це було за графіком. Це було задокументовано. Люди жалілися.

Одної п’ятниці інженер запустив міграцію схеми, яка включала скрипт очищення даних. У скрипті була помилка: він знаходив більше рядків, ніж потрібно.
Продакшн почав «втрачати» валідні записи. Моніторинг не одразу це помітив, бо QPS і показники помилок були нормальні. Дані стали просто… неправильні.

Вони виявили проблему через аномалії на рівні застосунку і швидко зупинили вилив. І тут питання:
«Чи можемо ми відновити на момент безпосередньо перед міграцією?» Це момент, коли команди дізнаються, чи PITR реальний.

Вони відновили останню фізичну базову копію в чистий інстанс, застосували binlog-и до хвилин перед міграцією за допомогою stop‑datetime,
перевірили підсумки за тим самим набором щомісячних запитів і переключили трафік. Увесь процес був практикований; ніхто не вчився mysqlbinlog під стресом.

Нудна щомісячна тренування не тільки врятувала дані. Вона зекономила час на прийняття рішень. Усі вже довіряли ранню процедуру, часам і перевіркам.
Ось як виглядає «операційна зрілість», коли це не презентація.

Поширені помилки: симптом → корінь проблеми → виправлення

1) «Відновлення SQLite іноді працює, іноді корумпує»

Симптоми: Відновлений файл відкривається періодично; відсутні останні зміни; «database disk image is malformed».

Корінь проблеми: Бекап здійснювався копіюванням основного файлу під час режиму WAL або під час активних записів; ігнорувалися -wal і -shm.

Виправлення: Використовуйте .backup або VACUUM INTO. Якщо використовуєте снапшоти файлової системи — робіть атомарні снапшоти й включайте стан WAL; запускайте перевірки цілісності на артефактах.

2) «PITR MariaDB провалився: відсутній binlog‑файл»

Симптоми: помилки mysqlbinlog: не вдається відкрити binlog; прогалини в послідовності binlog; відновлення зупиняється раніше.

Корінь проблеми: ретеншн binlog‑ів занадто короткий; ротація/очищення неправильно сконфігуровані; binlog-и зберігалися лише локально і загубилися разом із сервером.

Виправлення: збільште binlog_expire_logs_seconds відповідно до вікна виявлення + відновлення; архівуйте binlog-и у надійне сховище; налаштуйте алерти по відсутнім послідовностям.

3) «Логічний бекап пройшов, але відновлення неконсистентне»

Симптоми: помилки зовнішніх ключів; часткові дані; таблиці без рядків, які «повинні були бути».

Корінь проблеми: дамп зроблено без --single-transaction на InnoDB; паралельні записи створили неатомічний знімок.

Виправлення: використовуйте --single-transaction і уникайте дампів не‑транзакційних таблиць без планування; розгляньте фізичні бекапи для змішаних движків.

4) «PITR відновлює до неправильного моменту»

Симптоми: дані містять зміни, які мали бути виключені; відсутні зміни, які мали бути присутні.

Корінь проблеми: плутанина з часовими поясами; зсув системних годинників; stop‑datetime інтерпретовано інакше; ігнорування переходу на літній/зимовий час.

Виправлення: використовуйте UTC для серверів і runbook‑ів; фіксуйте час інцидентів в UTC; при потребі зупиняйтеся по позиції binlog/GTID, коли важлива точність.

5) «Бекапи проходять, але відновлення надто повільне для RTO»

Симптоми: відновлення займає години; розпакування домінує в часі; команда застосунку починає говорити про «прийнятну втрату даних» під час інциденту.

Корінь проблеми: стратегія оптимізована під вартість зберігання, а не під час відновлення; логічні відновлення використовуються в великому масштабі; середовище відновлення недостатньо потужне.

Виправлення: виміряйте відновлення, потім переструктуруйте: фізичні бекапи, швидші хости для відновлення, паралелізм або шардінг. Тримайте «гарячі» бекапи у форматі, придатному для швидкого відновлення.

6) «Бекапи викликають піки затримок у продакшні»

Симптоми: підвищена затримка запитів під час вікон бекапу; CPU завантажено; I/O wait росте.

Корінь проблеми: процес бекапу конкурує за I/O/CPU; важке стиснення на основному; снапшоти викликають копіювання‑по‑запису (COW) високу активність.

Виправлення: запускайте бекапи на репліках; обмежуйте CPU/I/O для робочих процесів бекапу; переносіть задачі компактування з пікового часу; тестуйте характеристики продуктивності снапшотів.

Чеклисти / покроковий план

Чеклист для рішення: обрати SQLite «просте відновлення» чи MariaDB «справжній PITR»

  • Чи є дані авторитетними? Якщо так, переважно MariaDB (або інший серверний DB) з PITR.
  • Чи потрібно відкотити помилку користувача? Якщо так — вам потрібен PITR. Снапшоти зазвичай надто грубі.
  • Наскільки швидко потрібно відновити? Якщо хвилини — уникайте повільних логічних шляхів відновлення.
  • Чи можете ви запускати і моніторити серверну БД? Якщо ні — SQLite з дисциплінованими бекапами і частими снапшотами може бути чеснішим вибором.

SQLite покроково: бекап, який реально відновлюється

  1. Підтвердіть режим журналу та чи використовується WAL.
  2. Використовуйте .backup або VACUUM INTO для створення консистентного артефакту.
  3. Зберігайте бекапи з версіонуванням (імена з часовими мітками або ID снапшотів).
  4. Запустіть PRAGMA integrity_check; на артефакті.
  5. Потренуйте відновлення: замініть файл БД, запустіть додаток, виконайте мінімальний health‑запит.
  6. Визначте вашу «PITR‑подібну» роздільну здатність: снапшот щогодини? щоп’ять хвилин? Будьте конкретні.

MariaDB покроково: базова копія + binlog‑и для PITR

  1. Увімкніть binlog-и і оберіть формат ROW.
  2. Налаштуйте ретеншн згідно з бізнес‑вимогами; архівуйте binlog‑и поза хостом, якщо хост може вмерти.
  3. Регулярно робіть базові бекапи (фізичні для великих наборів).
  4. Фіксуйте координати binlog (файл/позиція або GTID) в метаданих базової копії.
  5. Проведіть drill‑відновлення: відновіть базу в ізольований інстанс, застосуйте binlog‑и до обраного моменту, перевірте запитами, задокументуйте час.
  6. Операціоналізуйте: алерти на прогалини binlog, помилки бекапу, провали drills.

ЧАВО

1) Чи може SQLite робити «справжній» PITR?

Не в сенсі MariaDB. SQLite не надає першокласного журналу транзакцій, який можна відтворити до довільного моменту.
Ви можете наближати це частими снапшотами і ретельним обробленням WAL, але називайте це тим, чим воно є: відновлення на основі снапшотів.

2) Якщо я використовую снапшоти файлової системи, чи можна просто снепшотити файл SQLite?

Лише якщо ви розумієте режим журналу. У режимі WAL потрібен crash‑consistent снапшот основного файлу разом зі станом WAL.
Безпечніший за замовчуванням шлях — використовувати API бекапу SQLite, якщо снапшоти не координуються атомарно і не протестовані.

3) Чи достатньо реплікації в MariaDB, щоб відновитися після помилок?

Ні. Реплікація вірно відтворює помилки. Вона може допомогти, якщо ви маєте затриману репліку або можете швидко зупинити репліку,
але PITR все одно залежить від binlog‑ів і базової копії.

4) Чи потрібні фізичні бекапи для PITR у MariaDB?

Ні. Потрібна консистентна базова копія плюс binlog‑и. Базова копія може бути логічною або фізичною.
Фізична зазвичай є єдиним способом досягнути агресивного RTO в масштабі.

5) Чому б не робити mysqldump щоніч і вважати це справою виконаною?

Нічні дампи дають вам денну точку відновлення. Це підходить, якщо ваш RPO — день і ви готові до втрати даних.
Якщо вам потрібно «відкотити те, що сталося о 10:41», потрібні binlog‑и і операційна дисципліна навколо них.

6) Скільки зберігати binlog‑ів?

Зберігайте їх принаймні на тривалість потрібного вікна відновлення плюс вікно виявлення плюс запас.
Якщо ви типовo виявляєте проблеми за 72 години, але інколи через 10 днів, розраховуйте на 10 днів, а не на оптимістичний сценарій.

7) Який найнадійніший спосіб знати, що мої бекапи працюють?

Відновлюйте їх. Регулярно. Автоматично, коли можливо. Резервна копія без тестового відновлення — це надія, а не контроль.

8) Чи можна застосовувати binlog-и прямо в продакшн, щоб «відкотити» помилку?

Зазвичай: не робіть цього. Виконуйте PITR в ізольований інстанс, валідуйте, а потім переключайте або вибірково експортуйте виправлені дані.
Прямі маніпуляції в продакшні під час інциденту — як зробити одну помилку трилогією.

9) Чому відтворення binlog іноді падає з duplicate key або missing table?

Тому що ваша базова копія не відповідає потоку binlog, який ви відтворюєте (неправильні координати, неправильний сервер, інший набір даних),
або ви відновили часткову копію. Розглядайте метадані бекапу як частину бекапу, а не як декоративний додаток.

10) Що слід моніторити для здоров’я резервних копій?

Успішність задач бекапу — мінімум. Моніторьте: аномалії розміру артефактів, результати перевірки цілісності, часи drill‑відновлень,
покриття ретеншну binlog‑ів та вільний простір на джерелі і цілі зберігання.

Висновок: що робити наступного тижня

Якщо ви використовуєте SQLite — припиніть копіювати файл, ніби це JPEG. Використовуйте API бекапу, перевіряйте цілісність артефакту і виберіть частоту снапшотів, яку ви зможете захистити.
Якщо вам потрібні справжні семантики PITR, визнайте, що SQLite не створювався для цього, і перенесіть систему істини на серверну БД — або створіть журнал подій, що може відтворити істину.

Якщо ви використовуєте MariaDB — зробіть PITR реальним: увімкніть binlog-и, зберігайте та архівуйте їх; робіть консистентні базові копії;
фіксуйте координати; і відпрацьовуйте відновлення. Проведіть одне drill‑відновлення цього місяця. Заміряйте час. Запишіть несподіванки.
Потім виправте ці несподіванки, поки ніхто вас не викликає посеред ночі.

← Попередня
Proxmox «Не вдається видалити вузол»: безпечне видалення з кластера
Наступна →
HBM у звичайних GPU: мрія чи неминучість?

Залишити коментар