Остановить интернет-магазин на время копирования базы нельзя: в это время кто-то выбирает кроссовки, кто-то вводит номер карты, а кто-то уже нажал «Оформить». Но у этой истории есть и вторая сторона. Набор файлов, который скопирован без остановки, ещё не бэкап. Бэкап начинается там, где вы доказали, что из этих файлов поднимается база и в ней находятся нужные заказы.
Ниже разобран путь для магазина на MariaDB с таблицами InnoDB: снять физическую копию работающего сервера, подготовить её, привязать к бинарному журналу, развернуть в отдельном месте и найти в восстановленной базе заранее выбранные заказы. Условный магазин в примерах учебный, номера заказов тоже придуманы для разбора.
Что на самом деле значит «без остановки»
Утилита mariadb-backup копирует файлы работающего сервера, то есть делает физическую копию, а не выгрузку SQL-запросов. Для InnoDB документация описывает это как hot online backup, но сам метод называет nearly non-blocking: почти неблокирующим. Слово «почти» здесь важно. Это не обещание, что ни один запрос не заметит копирования (MariaDB: mariadb-backup Overview).
Причина понятна из устройства процесса. Файлы табличных пространств копируются отдельно, друг за другом, пока покупатели продолжают менять данные. Один файл будет снят чуть раньше, другой чуть позже, поэтому в момент копирования они не согласованы по единой точке. Одновременно отдельный поток читает InnoDB redo log, чтобы сохранить изменения, случившиеся за время получения файлов. Согласованность потом формируется подготовкой и восстановлением (MariaDB: How mariadb-backup Works).
В описанном процессе есть и фаза блокировки, нужная для согласованной точки, и заключительное освобождение блокировок. Поэтому честная формулировка для владельца магазина такая: заказы продолжают приниматься, а короткое окно удержания блокировок существует и должно быть измерено на вашей нагрузке, а не принято на веру.
Две стадии: снять файлы и сделать их пригодными
Полная копия запускается опцией --backup с каталогом --target-dir. Каталог должен либо отсутствовать, либо быть пустым: инструмент не смешивает новую копию со старой (MariaDB: Full Backup and Restore). Пример с учебными путями:
mariadb-backup --defaults-file=/etc/mariadb-backup.cnf --backup --target-dir=/backup/shop/2026-11-01Сразу после этой команды в каталоге лежит сырьё. Это файлы из разных моментов плюс записанный redo log. Запускать на них сервер нельзя. Нужна вторая стадия:
mariadb-backup --prepare --target-dir=/backup/shop/2026-11-01Во время prepare журнал применяется к файлам, и они сводятся к одному согласованному состоянию. Аналогия бытовая: фотографии сделаны с разных ракурсов, а prepare собирает из них один кадр. Для магазина вывод практический: копия, снятая в ночь и не прошедшая prepare, пока не годится для восстановления, как бы красиво ни выглядел размер каталога.
Разберём, что именно происходит с заказом, который попал в магазин прямо во время копирования. Допустим, файл таблицы заказов уже скопирован, а покупатель после этого оформил покупку. В самом файле копии новой строки нет, зато изменение осталось в redo log, который читался параллельно. При prepare журнал проигрывается поверх файлов, и строка появляется в согласованном состоянии. Если же пропустить эту стадию, таблица заказов окажется на одном моменте времени, а связанные с ней позиции и платежи могут оказаться на другом. Для магазина это самый неприятный вид поломки: база может даже не стартовать, а если стартует, то в ней легко получить заказ без товаров.
Поэтому после prepare каталог копии перестаёт быть промежуточным. Это единственный артефакт, который имеет смысл хранить и переносить: сырой каталог до подготовки лучше не оставлять рядом, чтобы в аварии никто не выбрал его по ошибке. Подпись с датой в имени каталога и отметка о том, что prepare прошёл, избавляют от этой путаницы лучше любой памяти дежурного (MariaDB: Full Backup and Restore).
Есть и обратный эффект. Повторно запускать prepare на уже подготовленной копии не нужно: каталог после первой подготовки уже содержит согласованное состояние. Если требуется несколько попыток восстановления, надёжнее сделать подготовку один раз, а затем каждый раз возвращать файлы через --copy-back, не трогая исходный каталог.
Одно условие касается версий. И для backup, и для prepare нужен инструмент, совместимый с исходной версией сервера. Если сервер на проде обновили, а на сервере с бэкапами остался старый пакет mariadb-backup, подготовка может не пройти. Версию инструмента и сервера стоит сверять заранее, а не в аварии. Эти данные к тому же записаны в метаданных копии.
Где prepare запускать
Для prepare не нужна аутентификация в работающем сервере, ему достаточно файлов копии. Поэтому тяжёлую подготовку удобно выполнять не на боевой машине, а на отдельной, где есть такая же версия инструмента. Это снимает с продакшена лишнюю нагрузку на диск и процессор. Если отдельной машины нет, prepare можно сделать на той же, но в тихое время и с оглядкой на свободное место.
Права и место: два узких места, а не весь Linux
Утилита читает файлы базы от имени своего пользователя ОС, поэтому у этого пользователя должен быть доступ к каталогу данных. Кроме того, внутри СУБД ей нужны глобальные права. Для типичных задач текущая документация называет RELOAD, PROCESS, LOCK TABLES и BINLOG MONITOR; отдельные режимы требуют дополнительных (MariaDB: mariadb-backup Overview).
Логин и пароль не обязательно писать в командную строку, где их увидят в списке процессов. Их можно положить в option file, в группу [mariadb-backup], которая поддерживает user и password:
[mariadb-backup]
user=backup_user
password=длинный_случайный_парольОпция --defaults-file указывает на такой файл и должна идти первым аргументом команды. Если поставить её после --backup, она не сработает так, как ожидается. Права на сам файл логично ограничить владельцем: пароль в нём единственный секрет всей процедуры.
С местом всё прозаично, но есть нюанс. Каталог назначения должен вместить физические данные базы, а не её сжатый дамп. Кроме того, во время самой prepare нужен запас: каталог растёт не сильно, но работать на последних процентах диска опасно. Если база магазина занимает, допустим, 60 ГБ, под одну копию разумно держать как минимум столько же свободного места плюс запас на журналы, и ещё место под вторую копию, пока старая не удалена. Это условный расчёт: реальный размер вы увидите по каталогу данных и по метаданным первой копии.
Тут и проявляется связь с ресурсами сервера. На VPS с NVMe копирование и prepare упираются в диск и процессор одновременно с самим магазином. Тариф меряют не названием, а свободным местом и запасом по вводу-выводу, и это проверяется замером на своей базе. Например, у тарифа Ba 40 ГБ NVMe, у Uab 80 ГБ, у Heka 160 ГБ, у Maat 240 ГБ: просто хранить копию рядом с базой на одном диске плохая идея, а сами цифры не обещают нужной ёмкости без замера.
Binlog: что случилось после снимка
Восстановленная копия возвращает базу на момент снимка. Покупатель, оформивший заказ через десять минут после копирования, в ней не найдётся. Чтобы дойти до нужной точки, нужны бинарные журналы. Для point-in-time recovery они должны быть включены ещё до сбоя: сначала восстанавливается базовая полная или инкрементальная копия, затем применяются события журналов до выбранной точки. Сам по себе возврат каталога из копии бинарные журналы не восстанавливает (MariaDB: Point-In-Time Recovery with mariadb-backup).
Здесь легко перепутать два механизма. Redo log InnoDB помогает привести к согласованности физические файлы самой копии, это работа prepare. Binary log фиксирует логические изменения, которые произошли уже после, и именно он нужен, чтобы «доиграть» новые заказы. Они не заменяют друг друга: без redo копия не запустится, без binlog вы потеряете всё, что случилось после неё.
Точка старта лежит в метаданных. Файл координат содержит имя бинарного журнала, позицию и gtid_current_pos. С MariaDB 11.1 он называется mariadb_backup_binlog_info, до 11.1 — xtrabackup_binlog_info. Версия сервера здесь меняет не идею, а имя файла, которое вы будете искать в каталоге (MariaDB: Files Created by mariadb-backup).
Дальше в примере из документации утилита mysqlbinlog строит SQL из журнала с начальной позицией и заданным временем завершения, а эксперимент идёт в отдельном новом datadir. Схема для магазина такая: берём позицию из файла координат, выбираем время, до которого нужно дойти, и получаем поток SQL-событий, который накатывается на подготовленную копию.
Разберём на учебных числах, зачем нужны и позиция, и время. Допустим, файл координат указывает на журнал и позицию, соответствующие снимку, а заказ № 10517 оформлен через десять минут после него. Если взять начальную позицию из файла, а время завершения поставить на пять минут позже снимка, SQL-поток дойдёт только до этого времени, и заказа № 10517 в стенде не будет, хотя журнал цел. Если же поставить время на полчаса позже, заказ появится, а вместе с ним и все изменения за эти полчаса. Так что граница по времени задаёт, до какого события вы возвращаете магазин, а позиция определяет, откуда журнал вообще начинает быть нужным (MariaDB: Point-In-Time Recovery with mariadb-backup).
Отсюда же вытекает требование к хранению: все файлы журнала от позиции в метаданных копии и до нужного момента должны существовать на момент восстановления. Если журналы ротируются и удаляются по сроку короче, чем интервал между копиями, цепочка рвётся, и заказы между последним доступным файлом и снимком вернуть нечем. Срок хранения журналов поэтому считают не от желания, а от самого редкого интервала между полными копиями плюс время, нужное, чтобы заметить проблему.
Ещё одна деталь касается самого каталога копии: файл координат лежит внутри неё, и именно он, а не дата создания каталога, говорит, с какого места продолжать. Копию, перенесённую на другой диск без этого файла, использовать для накатывания журнала уже нельзя (MariaDB: Files Created by mariadb-backup).
Когда координаты нельзя принимать на веру
Документация гарантирует согласованность этих координат с копией только если не использована опция --no-lock. Для режима без блокировок предусмотрен отдельный файл координат InnoDB, но при этом во время копирования не должно быть DDL и изменений нетранзакционных таблиц, иначе координаты могут оказаться устаревшими. Для магазина это значит: ускорять копирование таким способом нет смысла, если в базе идут миграции или остались таблицы Aria и MyISAM, которые меняются в процессе. Выигрыш в коротком окне блокировки не стоит сомнительной точки для накатывания журнала.
Про нетранзакционные таблицы стоит сказать отдельно. Описанное поведение hot online относится к InnoDB. Если в схеме магазина есть таблицы Aria или MyISAM, например старый справочник или служебный кэш, они не получают тех же гарантий автоматически. Перед внедрением процедуры полезно пройтись по схеме и посмотреть, какие движки реально используются, а таблицы с заказами, товарами, корзинами и платежами держать в InnoDB.
Есть и опция --lock-ddl-per-table: при ней метаданные таблицы блокируются от ALTER, RENAME, TRUNCATE и DROP на время операции с этой таблицей. Практическое следствие простое: если в ночное окно копирования попадает миграция схемы, она может ждать или мешать, поэтому расписание бэкапа и расписание выкладок лучше развести.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации Россия, США, Франция и Великобритания. Оплата картой РФ и по СБП.
Как узнать, сколько магазин «чувствовал» копирование
Среди метаданных backup_info есть версия инструмента и сервера, время начала и завершения копии и lock_time — время удержания блокировок. Префикс имени файла, как и у координат, зависит от версии. Это удобные числа для разговора о приемлемом окне: общая длительность копирования показывает, сколько времени диск был занят чтением, а lock_time — как долго действовала именно фаза блокировки.
Что считать приемлемым, определяет сам магазин. Условный пример: оформление заказа делает несколько запросов подряд, а приложение ждёт ответа базы до своего таймаута. Если время удержания блокировок остаётся заметно меньше этого таймаута, покупатель в худшем случае ощутит паузу, но не ошибку. Если сравнение показывает обратное, копию нужно переносить на менее нагруженное время или разгружать диск. Конкретные значения вы получите только из собственных запусков: снимите копию в рабочее время и в тихое, сравните lock_time с задержками в логах приложения.
Чтобы сравнение было предметным, можно свести два прогона в простую таблицу. Значения в ней условные: их нужно заменить вашими замерами.
| Показатель | Рабочее время | Тихое время |
|---|---|---|
| Длительность копирования | из backup_info | из backup_info |
| lock_time | из backup_info | из backup_info |
| Самый долгий запрос оформления в логах приложения | из логов | из логов |
| Ошибки таймаута за время копирования | из логов | из логов |
Смысл сравнения в том, что lock_time отвечает только за одну фазу. Долгая копия при маленьком lock_time означает, что магазин в основном делит с копированием диск, а не блокировки. Тогда лечить нужно ввод-вывод: вынести копию на другой том или сместить её на ночь. Большой lock_time говорит о другом: во время фазы блокировки что-то держало работу, и стоит посмотреть, не идёт ли в этот момент выкладка со сменой схемы или долгая транзакция (MariaDB: Files Created by mariadb-backup).
Так одно и то же слово «копирование мешает» распадается на две разные причины с разными способами лечения. Покупатель в обоих случаях видит медленную страницу, но чинят её по-разному.
Полезно проверить и поведение диска. Копирование читает много данных подряд, а магазин в этот момент пишет заказы и читает каталог. Если на сервере одна база и один диск, при плотном чтении выросшая задержка может проявиться не в блокировках, а в обычном замедлении запросов. Для этого достаточно наблюдать за временем ответа страницы оформления во время бэкапа.
Восстановление не поверх живой базы
Теперь главное: доказать, что копия работает. Делать это на продакшене нельзя, да и не нужно. Восстановление требует остановленного целевого сервера и пустого каталога данных, а значит, естественное место для проверки — отдельный сервер или отдельный экземпляр с чистым datadir (MariaDB: Full Backup and Restore). Отдельный небольшой VPS с root-доступом под такую проверку подходит хорошо: его можно создать, прогнать восстановление и удалить. Главное, чтобы на нём стояла версия MariaDB, совместимая с исходной; установку базы с нуля описывает статья Как установить и настроить MariaDB на VPS.
Порядок такой: остановить сервер на стенде, убедиться, что datadir пуст, выполнить prepare, если он ещё не сделан, и вернуть файлы:
mariadb-backup --prepare --target-dir=/backup/shop/2026-11-01
mariadb-backup --copy-back --target-dir=/backup/shop/2026-11-01Опция --copy-back сохраняет исходные файлы копии, а --move-back их перемещает. На стенде имеет смысл брать --copy-back: если что-то пойдёт не так, копия останется целой, и эксперимент можно повторить. --move-back экономит место, но тогда в случае ошибки придётся снимать копию заново.
После возврата файлов вспоминаем про владельца. Копирование выполнялось от одного пользователя, а сервер работает от другого, поэтому могут понадобиться права владельца на каталог данных. Типичный признак забытого шага — сервер, который отказывается стартовать с ошибкой доступа к файлам. Это не порча копии, а обычная смена владельца, и её исправляют до запуска.
Заказы-свидетели: что искать в поднятой базе
Если сервер запустился, это ещё не победа. Пустая база тоже запускается. Поэтому до копирования полезно выбрать несколько контрольных заказов и записать их номера. Сценарий для учебного магазина: заказ № 10482 оформлен за несколько минут до начала копирования и должен быть в базе сразу после prepare и copy-back. Заказ № 10517 создан уже после снимка, поэтому в восстановленной копии его ещё нет, и это нормально. Заказ № 10530 оформлен позже и должен появиться только после применения журнала.
Проверка складывается из трёх шагов. Сначала запрашиваем заказ № 10482 и смотрим не только саму строку, но и связанные позиции: сумма заказа должна сходиться с суммой его товаров. Затем убеждаемся, что заказа № 10517 нет: если он вдруг есть, значит, вы смотрите не ту копию или не тот каталог. Наконец, берём координаты из файла mariadb_backup_binlog_info (или xtrabackup_binlog_info для версий до 11.1), строим SQL из бинарного журнала утилитой mysqlbinlog с начальной позицией и временем завершения, накатываем его на стенд и снова ищем № 10517 и № 10530. Теперь они обязаны быть, если время завершения выбрано после их создания.
Такой набор заказов проверяет сразу несколько вещей. Первый показывает, что сама копия согласована. Второй показывает, что вы действительно восстановили состояние на момент снимка. Третий и четвёртый подтверждают, что координаты верны и журнал полон. Если журнал накатывается и заказ № 10517 не появился, причина обычно в одном из трёх мест: выбрана не та начальная позиция, нужные файлы журнала уже удалены или время завершения стоит раньше самого заказа.
Стоит выбрать и заказ, связанный с изменением схемы или с таблицей другого типа, если в магазине такие есть. Тогда вы заодно проверите самые рискованные места: те, где логика не сводится к простому InnoDB.
Сколько раз повторять, чтобы доверять
Одна удачная проверка говорит, что процедура работает сегодня. Через месяц сервер обновят, схему изменят, журналы начнут ротироваться по-другому. Разумно оформить восстановление как повторяемую операцию и запускать её регулярно на стенде, записывая результат: версия инструмента, время prepare, найдены ли контрольные заказы, сколько заняло накатывание журнала. Это даёт два важных числа: реальное время восстановления и понимание, достаточно ли хранить журналы за выбранный срок.
С ростом базы время prepare и copy-back растёт, и именно оно определяет, как долго магазин будет недоступен после настоящей аварии. Поэтому регулярный тест — это не формальность, а способ вовремя увидеть, что восстановление перестало укладываться в допустимое время, и добавить диска, процессора или перейти на более крупный план. Подбирать ресурсы стенда стоит по замерам: размер каталога данных и скорость диска важнее названия тарифа.
Заказ, который открылся
Процент скопированных файлов ничего не говорит о том, получится ли вернуть магазин. Его показывает другое: в восстановленной на отдельном сервере базе вы выполняете запрос и видите заказ № 10517 с покупателем, суммой и позициями, оформленный уже после снимка, а затем открываете его в тестовой копии витрины. Если он открылся и сумма сходится с учебной записью, значит, физическая копия, prepare, координаты binlog и накатанные события сложились в рабочую цепочку. До этого момента у вас были только файлы.