MySQL Backup - kopia zapasowa bazy danych

  • Data: 2014

Jak ważną sprawą jest regularne wykonywanie kopii zapasowych ważnych danych nawet nie wypada pisać. Wystarczy odwiedzić fora internetowe, gdzie pełno jest postów dotyczące utraty ultra ważnych danych. Początkującym użytkownikom, backup kojarzy się ze zgrywaniem plików/katalogów z jednego miejsca w drugie, często zapominając o kopii bazy danych. Jako że najpopularniejszą obecnie bazą danych jest MySQL, postaram się przybliżyć podstawy robienia kopii zapasowych.
Jest kilka sposobów na wykonanie kopii bezpieczeństwa bazy danych MySQL, dobór metody zależny jest od zastosowanego silnika. Korzystając z silnika MyISAM mamy do wyboru kilka metod. Pierwsza to kopiowane plików, druga to wykorzystanie narzędzia mysqldump. Natomiast jeśli używamy silnika InnoDB, który jest domyślny od wersji MySQL 5.5 lepiej nie ryzykować z kopiowaniem plików. Możemy również wykorzystać mysqldump lub bardzo dobrą aplikację Percona XtraBackup. Najprostszą i uniwersalną metodą niezależną od używanego przez bazę silnika jest mysqldump. Sprawa komplikuje się nieco, kiedy do zarchiwizowania jest duża porcja danych. Zrzut danych do formatu SQL bazy (MyISAM) o rozmiarze 3.3 GB trwało ~14 min na mało obciążonej maszynie (CPU: ATOM N2800 2 rdzenie/2 wątki, dysk 2 X 500 GB RAID 0/1) ale już jej przywrócenie trwało ~70 min. Ja skupię się na metodzie binarnej (kopiowanie plików) i na narzędziu mysqldump.
Jak już wcześniej pisałem podstawowym kryterium doboru metody wykonania kopii jest silnik bazy danych. Sprawdzić możemy na kilka sposobów np:

# mysqlshow -u userName --status nazwa_bazy_danych -p
Enter password:
Database: mysql
+---------------------------+--------+---------+------------+------+----------------+-------------+--------------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-------------------+----------+----------------+---------------------------------------------------+
| Name                      | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length    | Index_length | Data_free | Auto_increment | Create_time         | Update_time         | Check_time          | Collation         | Checksum | Create_options | Comment                                           |
+---------------------------+--------+---------+------------+------+----------------+-------------+--------------------+--------------+-----------+----------------+---------------------+---------------------+---------------------+-------------------+----------+----------------+---------------------------------------------------+
| columns_priv              | MyISAM | 10      | Fixed      | 0    | 0              | 0           | 227994731135631359 | 4096         | 0         |                | 2013-04-23 00:34:12 | 2013-04-23 00:34:12 |   

Znając już silnik bazy danych możemy przystąpić do działania.

Metoda binarna ( TYLKO MyISAM !!! )

  • maszyna_1
  • Lokalizujemy miejsce, gdzie znajdują się pliki baz danych poleceniem: grep datadir /etc/mysql/my.cnf (Debian) lub grep datadir /etc/my.cnf (Red Hat/Fedora/Centos), zakładam standardową lokalizację Debiana /var/lib/mysql
  • Blokujemy możliwość zapisywania danych do tabel na dwa sposoby:
    1. Wydając polecenie w konsoli MySQL: FLUSH TABLES WITH READ LOCK;
    2. Wyłączając serwer MySQL: /etc/init.d/mysql stop
  • Kopiujemy interesującą nas bazę: cp -R /var/lib/mysql/baza_danych /home/backup
  • Jeśli użyliśmy polecenia FLUSH TABLES..., to teraz należy zdjąć blokadę logując się do konsoli MySQL wydając polecenie UNLOCK TABLES;
  • Pozostaje skopiować katalog z bazą na drugą maszynę: scp -r /home/backup/baza_danych user@maszyna_2:/home/user
  • maszyna_2
  • Kopiujemy katalog bazy do katalogu gdzie są przechowywane katalogi z bazami: cp -R /home/user/dodana_baza /var/lib/mysql
  • Teraz można sprawdzić, że MySQL już widzi dodaną bazę:
  • # mysql -u user -p
    Enter password:
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 36
    Server version: 5.xxx
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | dodana_baza        |
    +--------------------+
    3 rows in set (0.00 sec)
    mysql> use dodana_baza
    Database changed
    mysql> show tables;
    ERROR 1018 (HY000): Can't read dir of './dodana_baza/' (errno: 13)
    
  • Jak widać na powyższym przykładzie, baza jest ale serwer MySQL nie ma do niej dostępu. Standardowo serwer MySQL działa z prawami użytkownika...mysql, więc zmieniamy prawa: chown -R mysql:mysql /var/lib/mysql/dodana_baza
  • Dla pewności sprawdźmy nową bazę poleceniem: mysqlcheck -u user dodana_baza -p

Narzędzie mysqldump

Bez wątpienia jest to chyba najpopularniejsza metoda backupu bazy MySQL. Mysqldump wykonuje zrzut danych do formatu SQL lub XML. Na początek kilka opcji:

Opis Znaczenie
-u username nazwa użytkownika
-p hasło hasło użytkownika
-h adres IP/nazwa domenowa adres zdalnego serwera
--port=numer portu port nasłuchu zdalnego serwera, jeśli jest inny niż 3306
--databases baza1 baza2... zrzut kilku baz jednocześnie
--all-databases zrzut wszystkich baz
--no-data zrzut struktury bazy pomijając dane
--no-create-info zrzut tylko samych danych bez struktury (tabele, pola, indeksy...)
--ignore-table=nazwa_tabeli pomija przy zrzucie tabelę o podanej nazwie
--add-drop-database przywracanie bazy danych przy jednoczesnym usunięciu istniejącej
--add-drop-table przywracanie tabeli przy jednoczesnym usunięciu istniejącej
--default-character-set=utf8 domyślne kodowanie znaków
--xml zrzut bazy danych do formatu xml

Wynik pracy narzędzia mysqldump jest przekazywany na standardowe wyjście, czyli najczęściej ekran monitora, dlatego my przekierujemy cały potok do pliku (np. polecenie > plik.out). NALEŻY PAMIĘTAĆ O ODPOWIEDNICH UPRAWNIENIACH UŻYTKOWNIKA DO BAZY DANYCH ! Zarówno po opcji -u jak i -p nie musimy używać spacji. W przypadku tworzenia kopii zapasowej z konsoli nie musimy podawać hasła, aplikacja sama się o nie zapyta i w związku z tym nie zapisze się w historii. Hasło musimy podać jedynie kiedy używamy mysqldump w skrypcie.

...i na koniec kilka przykładów:

Polecenie Znaczenie
zrzut lokalnej bazy danych mysqldump -uuserName -p nazwa_bazy > nazwa_bazy.sql
zrzut lokalnych baz danych mysqldump -uuserName -p --databases baza_1 baza_2 baza_3 > bazy.sql
zrzut wszystkich lokalnych baz danych mysqldump -uuserName -p --all-databases > wszytskie_bazy.sql
zrzut wybranych tabel mysqldump -uuserName -p nazwa_bazy nazwa_tabeli_1 nazwa_tabeli_2 > nazwa_bazy.sql
zrzut bazy danych z pominięciem wyszczególnionych tabel ( nazwa tabeli poprzedzona nazawą bazy !) mysqldump -uuserName -p -ignore-table nazwa_bazy.nazwa_tabeli > nazwa_bazy.sql
kopia samej struktury bazy bez danych mysqldump -uuserName -p --no-data nazwa_bazy_danych > nazwa_bazy_danych.sql
zrzut bazy danych do formatu xml, kodowanie utf-8 mysqldump -uuserName -p --default-character-set=utf8 --xml nazwa_bazy_danych > nazwa_bazy.xml
zrzut i kompresja bazy danych (bardzo efektywne w przypadku dużych baz) mysqldump -uuserName -p nazwa_bazy | gzip > nazwa_bazy.gz
zrzut bazy danych z jednoczesną kopią pliku na zdalny serwer mysqldump -uuserName -p nazwa_bazy | ssh userName@zdalny_host 'cat > /scieżka/nazwa_bazy.sql'
zrzut bazy danych ze zdalnego hosta mysqldump -h ip/domena_zdalnej_maszyny -uuserName -p nazwa_bazy > nazwa_bazy.sql

Backup bazy danych na zdalną maszynę wraz z aktualizacją

Często dostęp z zewnątrz do serwera MySQL jest zablokowany. Wtedy ostatnia pozaycja z powyższych przykładów nie zadziała. Można to łatwo obejść za pomocą ssh. Na zdalnym serwerze musi istnieć choćby pusta baza.

mysqldump -uroot -p hasło nazwa_bazy | ssh userName@zdalny_host mysql -uuserName -p hasło nazwa_bazy

Przywracanie kopii zapasowej bazy danych MySQL

Przywracanie bazy danych nie jest skomplikowane: mysql -uuserName nazwa_bazy < nazwa_bazy.sql -p, gdzie baza już musi istnieć.

Powrót »