полный и инкрементный backup баз Mysql

Thank you for reading this post, don't forget to subscribe!

В каче­стве при­ме­ра я рас­смот­рю сер­ве­ры с уста­нов­лен­ны­ми там про­дук­та­ми bitrix, рабо­та­ю­щи­ми в bitrixenv. Осо­бен­но­стью будет то, что bitrix до сих пор исполь­зу­ет не самую све­жую вер­сию mysql от percona — Percona Server for MySQL 5.7. Тем не менее, про­блем с этим нет ника­ких. Вер­сия будет под­дер­жи­вать­ся мини­мум до октяб­ря 2023 года.

Для пол­ных и инкре­мент­ных бэка­пов я рас­смот­рю ути­ли­ту Percona XtraBackup, кото­рая поз­во­ля­ет делать архи­вы баз дан­ных на лету без бло­ки­ро­вок таб­лиц. В моей ста­тье будет исполь­зо­вать­ся вер­сия 2.4, так как имен­но она под­дер­жи­ва­ет mysql 5.7. Это мак­си­маль­но доступ­ная вер­сия в репо­зи­то­ри­ях, кото­рые уста­нав­ли­ва­ет окру­же­ние bitrixenv.

При­ме­ры в этой ста­тье будут акту­аль­ны прак­ти­че­ски для всех вер­сий Mysql и XtraBackup, так как в под­хо­дах и коман­дах отли­чий почти нет. Важ­но знать, что послед­няя вер­сия XtraBackup на момент напи­са­ния ста­тьи была 8.0 и она под­дер­жи­ва­ет попу­ляр­ный форк mysql — MariaDB толь­ко до вер­сии 10.2 вклю­чи­тель­но, да и то с ого­вор­ка­ми. Для более позд­них вер­сий mariadb реко­мен­ду­ет­ся исполь­зо­вать mariabackup. Это форк XtraBackup, кото­рый в исполь­зо­ва­нии прак­ти­че­ски ничем не отли­ча­ет­ся от оригинала.

Установка Percona XtraBackup

С уста­нов­кой XtraBackup нет ника­ких про­блем и нюан­сов. Под все попу­ляр­ные дис­три­бу­ти­вы есть гото­вые паке­ты в офи­ци­аль­ном репо­зи­то­рии. Под­клю­ча­ем его в Centos.

Даль­ше ста­вим нуж­ную нам вер­сию про­грам­мы. Самую послед­нюю 8.0:

или 2.4

Обра­щаю вни­ма­ние, что если на сер­ве­ре с уста­нов­лен­ным bitrixenv уста­но­вить про­сто пакет xtrabackup, без ука­за­ния вер­сии, будет уста­нов­ле­на вер­сия 2.3, кото­рая не рабо­та­ет с устав­лен­ным там же по дефол­ту сер­ве­ром mysql 5.7.

Уста­нав­ли­ва­ем в Debian/Ubuntu:

И сам пакет:

Полный бэкап Mysql сервера

Итак, база дан­ных у нас рабо­та­ет, ути­ли­ту для бэка­па мы уста­но­ви­ли. Давай­те теперь сде­ла­ем пол­ный backup всех баз дан­ных наше­го сер­ве­ра mysql.

backup ини­ци­и­ру­ем про­це­ду­ру бэкапа
user=root поль­зо­ва­тель mysql
password=’R(zDXcVUmI[zwx%aNBTN’ пароль поль­зо­ва­те­ля, взя­тый в оди­нар­ные кавычки
target-dir=/root/backupdb/full дирек­то­рия для созда­ния пол­но­го бэка­па mysql

В даль­ней­ших при­ме­рах я не буду ука­зы­вать поль­зо­ва­те­ля и пароль, что­бы упро­стить коман­ды. Эти дан­ные я ука­зал в фай­ле ~/.my.cnf.

Мы сде­ла­ли пол­ный архив все­го mysql сер­ве­ра. В таком виде дан­ные не кон­си­стент­ны, так как они мог­ли менять­ся во вре­мя архи­ва­ции. Если вос­ста­но­вить их как есть, сер­вер mysql не запу­стит­ся. Будет ругать­ся на повре­жден­ные дан­ные. Что­бы вос­ста­но­вить целост­ность дан­ных, необ­хо­ди­мо выпол­нить еще одну команду.

После это­го бэкап будет пол­но­стью рабо­то­спо­со­бен и готов к вос­ста­нов­ле­нию. Я обыч­но выпол­няю эту коман­ду сра­зу же после бэка­па, но это не все­гда воз­мож­но. К при­ме­ру, если вы захо­ти­те его сра­зу же сжать.

В таком слу­чае его сна­ча­ла нуж­но будет рас­па­ко­вать, а потом под­го­то­вить. Делать это не обя­за­тель­но сра­зу. Мож­но хра­нить бэка­пы не под­го­тов­лен­ны­ми, а гото­вить толь­ко перед вос­ста­нов­ле­ни­ем, если это слу­чит­ся. Рас­па­ко­вы­ва­ет­ся бэкап сле­ду­ю­щим образом.

Для того, что­бы коман­да decompress отра­бо­та­ла без ошибки:

Необ­хо­ди­мо уста­но­вить пакет qpress.

Он есть в репо­зи­то­рии percona. После это­го рас­па­ков­ка прой­дет штатно.

Лич­но я не вижу боль­шо­го смыс­ла исполь­зо­вать клю­чи compress и decompress. Мож­но сде­лать пол­ный бэкап, под­го­то­вить его, а потом сжать тем же gzip.

На выхо­де полу­чи­те тот же архив, толь­ко сжат луч­ше и нет необ­хо­ди­мо­сти ста­вить допол­ни­тель­ный софт. Gzip и tar обыч­но есть во всех дис­три­бу­ти­вах. К тому же архив в виде еди­но­го фай­ла про­ще и быст­рее пере­дать на сер­вер бэка­пов и там хранить.

В завер­ше­нии раз­де­ла про пол­ный backup, пред­ла­гаю про­стень­кий скрипт для авто­ма­ти­за­ции про­цес­са через cron — mysql-full-backup.sh.

При выпол­не­нии это­го скрип­та раз в день, вы буде­те иметь отдель­ные пап­ки с име­нем в виде даты, а внут­ри пол­ный бэкап. Даль­ше мы в эти же пап­ки будем класть инкре­мент­ные бэка­пы. Но обо всем по порядку.

Инкрементный бэкап Mysql

Основ­ное удоб­ство XtraBackup как раз в про­стых, быст­рых и удоб­ных инкре­мент­ных бэка­пах для mysql. Допу­стим, по при­ме­ру выше, вы сде­ла­ли пол­ный бэкап. Он дол­жен быть не сжа­тый. Теперь на осно­ве это­го пол­но­го бэка­па, мож­но сде­лать инкре­мент­ный, где будут толь­ко изме­не­ния со вре­ме­ни пол­но­го бэкапа.

Мож­но про­ве­рить, что кон­крет­но в себя вклю­ча­ет пол­ный бэкап, а что инкре­мент. В дирек­то­рии с бэка­па­ми есть файл xtrabackup_checkpoints при­мер­но сле­ду­ю­ще­го содержания.

LSN — log sequence number. Это реги­стра­ци­он­ные номе­ра тран­зак­ций. В дан­ном слу­чае пол­ный бэкап начи­на­ет­ся с нуле­вой тран­зак­ции и закан­чи­ва­ет­ся 17687056. Теперь смот­рим этот же файл в дирек­то­рии inc1.

Инкре­мент­ный бэкап базы начал­ся с той тран­зак­ции, на кото­рой закон­чил­ся пол­ный. Сле­ду­ю­щий инкре­мент­ный архив может быть создан опять на базе пол­но­го, либо уже инкре­мент­но­го. То есть либо так:

либо так:

Може­те сами про­ве­рить, какие номе­ра тран­зак­ций будут в этих слу­ча­ях. Я обыч­но делаю раз в день пол­ный бэкап и потом инкре­мент­ные на осно­ве пол­но­го. Цепоч­ки инкре­мент­ных бэка­пов делать не люб­лю, так как если воз­ник­нут про­бле­мы с одним из архи­вов цепоч­ки, воз­ник­нут труд­но­сти с восстановлением.

Пред­ла­гаю вот такой скрипт для инкре­мент­ных бэка­пов — mysql-inc-backup.sh.

Може­те запус­кать его раз в час. Тогда вме­сте со скрип­том пол­но­го бэка­па, кото­рый выпол­ня­ет­ся раз в день, у вас будут вме­сте с ним в одной пап­ке инкре­мент­ные бэка­пы по часам. На сле­ду­ю­щий день мож­но запа­ко­вать всю дирек­то­рию с бэка­па­ми за про­шлый день и отпра­вить на сер­вер бэкапа.

Восстановление из бэкапа

Давай­те теперь вос­ста­но­вим дан­ные из сде­лан­но­го бэка­па. Если это тот же сер­вер, то все очень про­сто. Нам доста­точ­но под­го­то­вить бэкап с помо­щью клю­ча prepare, как я пока­зал ранее и заме­нить содер­жи­мое рабо­чей дирек­то­рии mysql на то, что хра­нит­ся в архиве.

Раз­би­ра­ем, что я сделал.

  1. Оста­но­вил mysql сер­вер и уда­лил все из ее рабо­чей директории.
  2. Вос­ста­но­вил дан­ные из архив­ной копии xtrabackup. По фак­ту он про­сто ско­пи­ро­вал дан­ные в рабо­чую дирек­то­рию mysql сервера.
  3. Назна­чил поль­зо­ва­те­ля mysql вла­дель­цем рабо­чей дирек­то­рии и все­го ее содержимого.
  4. Запу­стил mysql сер­вер с вос­ста­нов­лен­ны­ми данными.

После запус­ка mysql сер­ве­ра про­ве­ряй­те лог /var/log/mysql/error.log на пред­мет оши­бок. Если уви­ди­те там такие ошибки:

Зна­чит забы­ли выпол­нить под­го­тов­ку архи­ва перед вос­ста­нов­ле­ни­ем. Я частень­ко это забы­ваю и рас­стра­и­ва­юсь, когда вижу ошиб­ки. В общем слу­чае оши­бок после вос­ста­нов­ле­ния быть не должно.

Если буде­те вос­ста­нав­ли­вать базу на дру­гой сер­вер, то после­до­ва­тель­ность дей­ствий будет сле­ду­ю­щая. Под­клю­ча­ем репо­зи­то­рий percona.

Ста­вим mysql server и xtrabackup нуж­ной версии.

Копи­ру­ем на новый сер­вер архив сер­ве­ра баз данных.

Рас­па­ко­вы­ва­ем его:

Вос­ста­нав­ли­ва­ем дан­ные и запус­ка­ем mysql сервер.

Захо­дим в кон­соль mysql и про­ве­ря­ем спи­сок баз и пользователей.

Все на месте, как и на исход­ном сервере.

Это я пока­зал вос­ста­нов­ле­ние из пол­но­го бэка­па. Теперь пока­зы­ваю, как вос­ста­но­вить­ся из инкре­мент­ной копии. Для нача­ла нам надо под­го­то­вить пол­ную копию для нака­ты­ва­ния на нее инкремента.

Теперь добав­ля­ем туда дан­ные из инкре­мент­но­го бэкапа.

И так для всех осталь­ных инкре­мент­ных копий, если у вас из них выстро­е­на цепоч­ка. Кон­тро­ли­ро­вать состо­я­ние пол­но­го архи­ва и сопо­став­лять с инкре­мен­та­ми мож­но по содер­жи­мо­му фай­лов xtrabackup_checkpoints. После того, как вос­ста­но­ви­ли все инкре­мент­ные архи­вы, на послед­нем из них не нуж­но исполь­зо­вать ключ apply-log-only. Так же он не нужен, если у вас толь­ко одна инкре­мент­ная копия. Завер­ша­ю­щий этап под­го­тов­ки пол­ной копии дол­жен быть без него.

После того, как вос­ста­но­ви­ли всю цепоч­ку инкре­мен­тов, с архи­вом мож­но рабо­тать как с обыч­ным пол­ным бэкапом.

Бэкап отдельной таблицы или базы

Не все­гда нуж­ны архив­ные копии все­го mysql сер­ве­ра. Ино­гда доста­точ­но отдель­ной базы дан­ных или даже таб­ли­цы. Xtrabackup поз­во­ля­ет это сде­лать. Архи­ви­ру­ем толь­ко одну базу дан­ных sitemanager.

Для того, что­бы этот спо­соб бэка­па отдель­ной базы mysql рабо­тал, необ­хо­дим пара­метр innodb_file_per_table в настрой­ка сер­ве­ра баз данных.

Вос­ста­нов­ле­ние отдель­ной базы mysql будет выгля­деть так.

Мы по сути про­сто ско­пи­ро­ва­ли исход­ные фай­лы базы из бэка­па в рабо­чий ката­лог, пред­ва­ри­тель­но сохра­нив преды­ду­щую вер­сию базы на вся­кий случай.

Теперь попро­бу­ем из пол­но­го бэка­па базы вос­ста­но­вить толь­ко одну таб­ли­цу. В моем при­ме­ре я на рабо­та­ю­щем сер­ве­ре сде­лаю вос­ста­нов­ле­ние суще­ству­ю­щей таб­ли­цы из пол­но­го бэка­па. Если буде­те вос­ста­нав­ли­вать на дру­гой сер­вер, то перед этим вам нуж­но будет вос­со­здать исход­ную струк­ту­ру таб­ли­цы перед тем, как буде­те вос­ста­нав­ли­вать дан­ные по пред­ло­жен­но­му методу.

Гото­вим бэкап к восстановлению:

Идем в кон­соль mysql и выби­ра­ем там таб­ли­цу для вос­ста­нов­ле­ния. В моем при­ме­ре это будет таб­ли­ца b_user_access из базы sitemanager. Смот­рим, запол­не­на ли таб­ли­ца данными.

Дела­ем DISCARD этой таблицы.

Discard озна­ча­ет, что будет уда­лен ibd файл таб­ли­цы. Теперь нам его нуж­но ско­пи­ро­вать из бэка­па и назна­чить пра­ва для mysql.

Воз­вра­ща­ем­ся в кон­соль mysql и импор­ти­ру­ем данные.

Смот­рим, что получилось.

Дан­ные вос­ста­нов­ле­ны. Вер­ну­лись те же 6 строк, что и были до этого.

Бэкап и восстановление mysql с помощью mysqldump

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

Бэкап всех баз mysql сер­ве­ра с его помощью:

Мож­но сра­зу же сжи­мать его.

Бэкап кон­крет­ной базы данных.

Мне чаще все­го меша­ют в дам­пе коман­ды на созда­ние базы дан­ных — CREATE DATABASE, поэто­му я их уби­раю клю­чом no-create-db.

Для того, что­бы вос­ста­но­вить базу дан­ных из дам­па, мож­но вос­поль­зо­вать­ся сле­ду­ю­щи­ми коман­да­ми. Выпол­ня­ют­ся из кон­со­ли mysql.

Если дамп без коман­ды на созда­ние базы дан­ных и ее нет у вас на сер­ве­ре, то не забудь­те ее перед этим создать. Так же вос­ста­но­вить базу дан­ных из дам­па мож­но сле­ду­ю­щим образом.

Вот про­стень­кий скрипт, кото­рый поз­во­ля­ет забэка­пить все базы дан­ных сер­ве­ра, при этом бэкап каж­дой базы будет в отдель­ном фай­ле. Это удоб­нее, чем все базы еди­ным фай­лом. Отту­да потом труд­но доста­вать кон­крет­ную базу.

Так же могу поре­ко­мен­до­вать вот этот скрипт для бэка­па — https://github.com/adegtyarev/mysqlbackup. Опи­сы­вать его не буду, по ком­мен­та­ри­ям в скрип­те поня­тен его функционал.

Если вам нуж­но из пол­но­го бэка­па mysql вос­ста­но­вить отдель­ную таб­ли­цу, то ее мож­но выде­лить из пол­но­го дам­па через обыч­ный awk при­мер­но вот так.

Даль­ше через source мож­но вос­ста­но­вить дан­ные из это­го дам­па отдель­ной таблицы.

Ино­гда быва­ет полез­но сде­лать не про­сто пол­ный backup базы дан­ных, а раз­бить его сра­зу на таб­ли­цы. Тут помо­жет сле­ду­ю­щий скрипт.

В таком вари­ан­те он сде­ла­ет потаб­лич­ный бэкап всех баз дан­ных. Если вам не нуж­ны все базы, то в цик­ле може­те вме­сто пред­ло­жен­но­го пере­бо­ра всех суще­ству­ю­щих баз ука­зать одну конкретную.

Вос­ста­но­вить потом всю базу из тако­го потаб­лич­но­го бэка­па мож­но таким образом.

При исполь­зо­ва­нии паро­ля в откры­том виде в mysql или mysqldump, в кон­соль посто­ян­но сыпят­ся предупреждения.

Что­бы их не было, пере­не­си­те, как я пока­зы­вал выше, пароль в отдель­ный файл ~/.my.cnf, а из скрип­та убе­ри­те авто­ри­за­цию вообще.