Потеря данных из-за сбоя БД или ошибки администратора обходится бизнесу в среднем от 50 000 до 500 000 рублей за час простоя, не считая репутационных потерь. Самописный скрипт на PHP для бэкапов — это единственный способ гарантировать независимость от ограничений хостинга и обеспечить RPO (Recovery Point Objective) в пределах 15-60 минут.
Технические ограничения mysqldump и PHP
Основная проблема при реализации бэкапа через PHP — лимит max_execution_time и memory_limit. При объеме БД свыше 500 МБ стандартный вызов exec('mysqldump ...') часто обрывается по таймауту сервера (обычно 30-60 секунд), оставляя битый .sql файл. В таких случаях необходимо использовать флаг --single-transaction для InnoDB, чтобы избежать блокировки таблиц и простоя сайта на время выгрузки.
Кейс: проект с базой 2 ГБ при попытке бэкапа через PHP-скрипт вызывал 503 ошибку и перегрузку CPU до 90% на 3 минуты. Решение: перенос логики в фоновый процесс через nohup и использование потоковой записи в файл, что снизило нагрузку на CPU до 15-20%.
Экспертный вывод: никогда не используйте SELECT-запросы для формирования бэкапа вручную — это в 5-7 раз медленнее, чем системный дамп.
Стратегия хранения: локально против удаленно
Хранить бэкапы на том же диске, где лежит сайт — критическая ошибка. При атаке через уязвимости, которые описываются в разделе Безопасность готовых PHP-решений, злоумышленник удаляет бэкапы первым делом. Оптимальный стек: локальный временный файл $
ightarrow$ сжатие Gzip $
ightarrow$ отправка по SSH/SFTP или API облачного хранилища (S3). Сжатие Gzip сокращает объем SQL-дампа в 4-6 раз, что критично при передаче по сети.
Сравнение: хранение на VPS (риск 100% потери при сбое RAID) против S3-хранилища (стоимость около $0.023 за ГБ, надежность 99.9%). Для базы в 10 ГБ с ежедневным циклом за 30 дней затраты составят менее $10 в месяц.
Экспертный вывод: используйте схему «3-2-1»: три копии, два разных носителя, один вне офиса/сервера.
Автоматизация через Cron и проверка целостности
Скрипт бесполезен, если он перестал работать, а вы заметили это через месяц. Настройка Cron на запуск каждые 6 или 12 часов — стандарт, но обязательным должен быть механизм Health Check. Скрипт должен отправлять уведомление в Telegram/Email только в случае ошибки или, наоборот, подтверждать успешное создание файла размером более 0 КБ.
Пример: в 15% случаев бэкапы оказываются «пустыми» из-за переполнения дискового пространства (/tmp). Внедрение проверки filesize() перед отправкой в облако позволяет обнаружить проблему за 1 цикл бэкапа, а не в момент восстановления.
Экспертный вывод: бэкап считается существующим только после успешного тестового восстановления. Проводите drill-тест раз в квартал.
Безопасность данных и прав доступа
Самая частая ошибка — хранение пароля от БД в открытом виде в .php файле в корне сайта. Если сервер настроен некорректно, файл может быть прочитан через браузер. Правильный подход: вынос конфига за пределы public_html или использование переменных окружения (.env). Права на папку с бэкапами должны быть строго 700 или 750, чтобы исключить доступ других пользователей сервера.
Мини-кейс: утечка данных клиента произошла из-за того, что папка /backups была доступна по прямой ссылке. Внедрение проверки HTTP_REFERER или перенос папки выше корня сайта полностью закрывает эту дыру.
Экспертный вывод: используйте отдельного пользователя MySQL с правами только на LOCK TABLES и SELECT, чтобы минимизировать ущерб при компрометации скрипта.
Вывод
Для баз данных до 5 ГБ оптимальным выбором будет PHP-скрипт, вызывающий mysqldump с последующей отправкой в S3-хранилище через AWS SDK. Избегайте плагинов CMS для бэкапов — они создают избыточную нагрузку на интерпретатор и часто зависают. Начните с настройки Cron-задачи раз в 12 часов, вынесите конфиг за пределы публичного доступа и обязательно настройте уведомления о сбоях в Telegram, иначе вы узнаете о проблеме слишком поздно.