MySQL: резервное копирование и восстановление баз

Большинство хостинг-провайдеров производят резервное копирование всех файлов пользователей. Однако, не стоит забывать о том, что хостеры делают backup, в основном, для себя, на случай аварии. Именно по этой причине пользователи в условиях хостинга могут, конечно, рассчитывать на восстановление в случае удаления каких-то данных по вине самого пользователя, но вовсе не факт, что провайдер сделает восстановление MySQL-базы сразу по получению запроса. Лучше делать для себя копию и в случае чего ее использовать. Можно даже периодически копировать этот backup на другой сервер.

Сделать копию всех статических html-файлов и прочих документов достаточно просто. Так же несложно периодически архивировать и копировать скрипты. Сложней представляется задача создания копии (далее backup) такой динамичной структуры, как база данных MySQL. Основные трудности, которые возникают перед администратором размещенного на хостинге сайта, обычно бывают такие:

  1. Отсутствие физического доступа к файлам базы данных. Как правило, провайдеры хостинга предоставляют возможность работы с базой данных только через скрипты или специальный mysql-клиент, но не дают прав на доступ непосредственно к файлам, в которых содержатся данные из MySQL-базы.
  2. Отсутствие у администратора знаний о том, как вообще надо делать backup. Обычно такая задача возникает только, когда «клюнул жареный петух». То есть, в случае аварии, вторжения хакеров или в других внештатных ситуациях. Веб-мастеры просто не готовы к немедленному backup и начинают судорожно изучать документацию по MySQL, а время идет…
  3. В случае, если веб-мастер не владеет в достаточной мере навыками работы со специализированными утилитами из пакета MySQL, могут возникать трудности, связанные с ограничениями, налагаемыми хостинг-провайдером на пользовательские аккаунты. Например, если база очень большая и ее размер превышает лимит на доступную пользователю память (RAM), backup сделать будет сложно. Нужно пользоваться тонкими настройками утилит резервного копирования, что иногда тоже вызывает трудности на практике.

Далее рассмотрим способ создания резервных копий MySQL-баз.

Как сделать резервную копию базы данных MySQL

Существует программа mysqldump, позволяющая быстро и просто производить операции по созданию резервных копий баз MySQL. Также mysqldump дает возможность делать очень тонкие настройки для управления процессом создания резервных копий баз данных или отдельных таблиц. Можно сказать, что mysqldump — это основной инструмент, которым Вам придется пользоваться в том случае, если Вы будете делать backup MySQL.

Сразу возьмем простую задачу, которую будем решать с помощью mysqldump, и разберемся, что к чему. Есть хостинг, есть база данных DBNAME, которую выделил Вам хостинг-провайдер. Есть хост HOST, на котором размещен сервер MySQL, логин LOGIN к нему, порт PORT, на котором работает сервер, а также пароль PASS. Имея все эти данные, можно сделать dump (дамп, копию) базы DBNAME так (выполняем в unix shell):

> mysqldump -uLOGIN -PPORT -hHOST -pPASS DBNAME > dump.sql

После выполнения данной команды в файле dump.sql у нас будет копия MySQL-базы DBNAME. Это произойдет только в том случае, конечно, если все параметры заданы верно, в соответствии с настройками хостинга. Сразу нужно сказать, что программа mysqldump производит вывод результатов прямо Вам на STDIN, то есть на экран. Нужно перенаправлять вывод в какой-либо файл. Например, как в данном случае — » > dump.sql «. Если этого не сделать, а база большая, Вы получите на экран все те мегабайты информации, которые в ней содержатся.

Mysqldump — это программа, создающая сценарий восстановления данных базы mysql. То есть, вывод mysqldump — это не какие-то абстрактные и нечитаемые двоичные данные, а осмысленный текст сценария. Например, если в Вашей базе «files» была таблица «restore» c полем «copy», имеющим тип данных integer, и одна-единственная запись «1234567», то mysqldump создаст примерно такой сценарий:

# MySQL dump 8.14
#
# Host: localhost Database: files
#--------------------------------------------------------
# Server version 3.23.39-log

#
# Table structure for table 'restore'
#

CREATE TABLE restore (
 copy int(11) default NULL
) TYPE=MyISAM;

#
# Dumping data for table 'restore'
#

INSERT INTO copy VALUES ('1234567');

Таким образом, mysqldump сделает описание структур таблиц и создаст INSERT-команды для восстановления данных. Итак, мы перенаправляем вывод mysqldump в текстовый файл «dump.sql», который потом будем использовать для восстановления. Рассмотрим и этот процесс — восстановление базы данных из резервной копии.

Восстановление базы данных MySQL из резервной копии

Для восстановления будем использовать программу mysql, которая входит в комплект поставки MySQL наряду с mysqldump. Допустим, у нас имеется backup в файле dump.sql. Нам нужно восстановить его в рабочую базу. Например, была случайно удалены все таблицы база данных, а теперь пытаемся восстановить их из резервной копии. Делаем так :

> mysql -uLOGIN -PPORT -hHOST -pPASS DBNAME < dump.sql 

То есть, заставляем mysql-клиент соединиться с сервером и выполнить сценарий, который у нас имеется. После выполнения этой команды в Вашей базе появятся таблицы и данные из резервной копии. Учитывайте то, что данные будут просто создаваться по сценарию из dump.sql. Другими словами, если таблицы, которые упоминаются в дампе базы, уже существуют и имеют другую структуру, тогда явно возникнет ошибка. Просто посмотрите на сценарий и на рабочую базу и представьте, что Вы вручную выполняете команды из сценария. Если уверены, что все будет хорошо — смело восстанавливайте.

Рассмотрим более тонкие настройки mysqldump:

—databases позволяет сделать так, что mysqldump включит в сценарий восстановления команды CREATE DATABASE /*!33333 IF NOT EXISTS*/ DBNAME и USE DBNAME. Это позволит создавать рабочие базы «с нуля». То есть, без использования —databases подразумевается, что пользователь восстанавливает одну базу данных и явно указывает, куда нужно помещать восстанавливаемые данные. Если же backup создается с целью сделать полностью рабочую копию данных, например, на другом MySQL-сервере, то нужно использовать этот ключ;

—all-databases позволяет сделать копии всех баз данных, которые существуют на данном MySQL-сервере. Если же нужно сделать копии только некоторых баз, нужно просто указать их через пробел при вызове mysqldump из командной строки (см. выше);

Ключ —help. Программа mysqldump имеет множество версий. Посмотреть, какие возможности поддерживаются конкретно Вашей версией, можно с помощью этого ключа;

—add-drop-table — ключ, который заставит mysqldump добавлять в итоговый сценарий команду drop table перед созданием таблиц. Это позволит избежать некоторых ошибок при восстановлении базы из резервной копии. Конечно, нужно учитывать то, что таблицы, находящиеся в рабочей копии (если таблицы с таким же именем существуют в backup), перед восстановлением из резервной копии будут удалены из основной базы и пересозданы из backup;

—no-data. С помощью этого ключа можно быстро сделать копию структуры таблицы/баз без самих данных. Например, Вы создали сложную таблицу и хотели бы сохранить на будущее ее структуру, а сами данные, которые находятся в этой таблице, Вам в резервной копии не нужны;

—result-file=… — этот ключ можно использовать для перенаправления вывода в файл. Можно использовать обычное unix-перенаправление командой «>», а можно — вот этот ключ. Кому что нравится;

Кроме перечисленных ключей mysqldump имеет и еще некоторое количество очень полезных возможностей, которые Вы можете применять по обстоятельствам. Полная документация по mysqldump доступна на странице http://www.mysql.com/doc/m/y/mysqldump.html.

Еще один очень полезный совет по использованию mysqldump в хостинговой среде. Как правило, при использовании хостинга на пользователя налагаются некоторые ограничения. Например, нельзя занять больше некоторого количества физической памяти (RAM, ОЗУ). mysqldump по умолчанию помещает все полученные от MySQL-сервера данные в память, а потом записывает все это на диск. Соответственно, если провайдер дает Вам занять, например, 30Мб памяти, а база, копию которой Вы делаете с помощью mysqldump, занимает 50Мб, конечно, тут возникнет ошибка — mysqldump не сможет отработать корректно и завершится аварийно, о чем Вам сообщит. Чтобы «заставить» mysqldump писать данные сразу на диск, а не хранить их, пусть даже и временно, в памяти, используйте ключ —quick. Это решит проблему.

Автоматизация копирования резервных копий баз

Теперь подумаем, как бы нам автоматизировать процесс создания резервных копий базы данных. Итак, существует программа — cron. Она позволяет запускать процессы в указанное пользователем время или с определенной периодичностью. Сразу оговоримся — cron в общем случае существует только под Unix, так что, если Вы используете для хостинга ОС Windows, проконсультируйтесь со своим хостинг-провайдером о том, как лучше запускать процессы в нужное время. Да и вообще, пожалуй, этот пункт будет интересен только unix-пользователям.

В unix shell запускаем crontab -e и создаем такое правило запуска процесса создания копий базы:

0 0 * * * mysqldump -uLOGIN -PPORT -hHOST -pPASS DBNAME
	| gzip -c > `date "+%Y-%m-%d"`.gz 

Эта команда, запускаясь из cron в полночь (00:00) каждых суток, делает дамп Вашей базы DBNAME и архивирует его архиватором gzip в файл-архив с именем, соответствующим текущей дате. Например, если мы делаем dump 15 февраля 2016 года, имя файла с архивом будет 2016-02-15.gz. Для того, чтобы получить файлы, по именам которых можно удобно узнать дату их создания, используется команда date, которая является стандартной для всех unix-систем. Эта команда позволяет задавать произвольный формат вывода даты, что мы и использовали — date «+%Y-%m-%d». Мы поместили эту команду в обратные одинарные кавычки (backticks), что в unix shell позволяет вставить результат выполнения другой команды.

Сохраняем правило для cron и ждем результатов. Итак, каждый день мы будем иметь на диске заархивированную копию нашей базы данных. Можно быстро найти нужный архив по его названию и восстановить то, что испортилось, например. Кстати, если Вы хотите автоматизировать удаление старых архивов, попробуйте воспользоваться cron и командой find, которая обычно есть в unix. Запуская периодически find ~/каталог-с-архивами -name «*.gz» -mtime +7, Вы будете удалять архивы, которые «старше» семи дней. Прочитайте документацию по find — она доступна по команде man find в unix shell.

Если у Вас есть компьютер, постоянно подключенный к интернет, или другой хостинг, тогда можно так же по cron копировать созданный Вами backup на нее. Используйте для копирования на другую машину команды ftp и scp. Добавьте их запуск в cron. Если Ваша машина поддерживает соединение по протоколу ssh, используйте secure copy клиент для копирования файлов — scp. Читайте документацию по этой команде в man-странице man scp. Примерный запуск: scp 2016-02-15.gz : — закачиваем файл 2016-02-15.gz на сервер your.host.ru авторизовавшись там под логином login.

Для более гибкой настройки и автоматизации процесса резервного копирования можно воспользоваться и скриптом mysqlhotcopy, написанный на языке Perl.