Відновлення на момент у часі (point-in-time recovery, PITR) = останній повний бекап + бінарний журнал від моменту бекапу до потрібної точки.
Що потрібно мати заздалегідь:
- регулярний повний бекап з відомою позицією бінарного журналу (
mysqldump --single-transaction --source-data=2записує її в дамп коментарем; фізичні інструменти - у свої метадані); - бінарні журнали, що зберігаються довше за інтервал між бекапами, і бажано копіюються на інший сервер (якщо загине диск, разом із ним загинуть і журнали).
Сценарій: о 14:32 хтось виконав DELETE FROM orders без WHERE. Бекап зроблено о 03:00.
1. Зупинити запис у базу (режим обслуговування), щоб не накопичувати зміни поверх аварії. Скопіювати поточні бінарні журнали в безпечне місце.
2. Знайти точну позицію помилки:
mysqlbinlog --base64-output=DECODE-ROWS --verbose \
--start-datetime="2026-10-04 14:30:00" --stop-datetime="2026-10-04 14:35:00" \
binlog.000057 | grep -n -B5 "DELETE FROM \`app\`.\`orders\`"
# знаходимо "# at 48211337" перед подією
3. Відновити бекап на окремому сервері (не поверх продакшену):
mysql app < backup-03-00.sql
4. Застосувати журнал від позиції бекапу до позиції перед DELETE:
# позиція з дампу: -- CHANGE REPLICATION SOURCE TO SOURCE_LOG_FILE='binlog.000055', SOURCE_LOG_POS=157;
mysqlbinlog --start-position=157 binlog.000055 binlog.000056 > /tmp/redo.sql
mysqlbinlog --stop-position=48211337 binlog.000057 >> /tmp/redo.sql
mysql app < /tmp/redo.sql
З GTID зручніше: --exclude-gtids для транзакції з DELETE і --skip-gtids залежно від сценарію.
5. Що робити з даними після аварії. Події після DELETE (нові замовлення з 14:32 до зупинки) теж є в журналі. Можна:
- застосувати журнал після помилкової транзакції (
--start-positionна наступну подію), пропустивши лише її; - або відновити на окремому сервері лише постраждалу таблицю й перенести видалені рядки на продакшен, не відкочуючи всю базу.
Другий варіант часто кращий: решта бази живе далі, а виправляється лише зламане.
Нюанси:
--start-datetime/--stop-datetimeнеточні (секундна точність, в одну секунду - багато подій) - для точки зупинки краще позиція чи GTID;- застосовувати журнали кількох файлів треба одним потоком
mysqlbinlogчи по черзі без пропусків; - відновлення великої бази з логічного дампу займає години - це час простою, який треба знати заздалегідь (RTO).
Захист від таких аварій до бекапів: відкладена репліка (SOURCE_DELAY), обмежені права застосунку й sql_safe_updates у консольних сесіях.
Докладніше в документації: Відновлення на момент у часі через бінарний журнал