Mysqldump er det mest populære logiske sikkerhedskopieringsværktøj til MySQL. Det er inkluderet i MySQL-distributionen, så det er klar til brug på alle MySQL-forekomster.
Logiske sikkerhedskopier er dog ikke den hurtigste eller mest pladseffektive måde at sikkerhedskopiere MySQL-databaser på, men de har en kæmpe fordel i forhold til fysiske sikkerhedskopier.
Fysiske sikkerhedskopier er normalt alle eller intet slags sikkerhedskopier. Selvom det måske er muligt at oprette delvis backup med Xtrabackup (vi beskrev dette i et af vores tidligere blogindlæg), er det vanskeligt og tidskrævende at gendanne en sådan backup.
Grundlæggende, hvis vi ønsker at gendanne en enkelt tabel, er vi nødt til at stoppe hele replikeringskæden og udføre gendannelsen på alle noderne på én gang. Dette er et stort problem - i disse dage har du sjældent råd til at stoppe alle databaserne.
Et andet problem er, at tabelniveauet er det laveste granularitetsniveau, du kan opnå med Xtrabackup:du kan gendanne en enkelt tabel, men du kan ikke gendanne en del af den. Logisk backup kan dog gendannes i den måde, hvorpå SQL-sætninger køres, derfor kan den nemt udføres på en kørende klynge, og du kan (vi ville ikke kalde det nemt, men stadig) vælge hvilke SQL-sætninger, der skal køres, så du kan lav en delvis gendannelse af en tabel.
Lad os tage et kig på, hvordan dette kan gøres i den virkelige verden.
Gendannelse af en enkelt MySQL-tabel ved hjælp af mysqldump
I begyndelsen skal du huske på, at delvise sikkerhedskopier ikke giver en ensartet visning af dataene. Når du tager sikkerhedskopier af separate tabeller, kan du ikke gendanne en sådan sikkerhedskopi til en kendt position i tide (for eksempel for at klargøre replikeringsslaven), selvom du ville gendanne alle data fra sikkerhedskopien. Lad os fortsætte, når vi har det bag os.
Vi har en herre og en slave:
Datasættet indeholder et skema og flere tabeller:
mysql> SHOW SCHEMAS;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sbtest |
| sys |
+--------------------+
5 rows in set (0.01 sec)
mysql> SHOW TABLES FROM sbtest;
+------------------+
| Tables_in_sbtest |
+------------------+
| sbtest1 |
| sbtest10 |
| sbtest11 |
| sbtest12 |
| sbtest13 |
| sbtest14 |
| sbtest15 |
| sbtest16 |
| sbtest17 |
| sbtest18 |
| sbtest19 |
| sbtest2 |
| sbtest20 |
| sbtest21 |
| sbtest22 |
| sbtest23 |
| sbtest24 |
| sbtest25 |
| sbtest26 |
| sbtest27 |
| sbtest28 |
| sbtest29 |
| sbtest3 |
| sbtest30 |
| sbtest31 |
| sbtest32 |
| sbtest4 |
| sbtest5 |
| sbtest6 |
| sbtest7 |
| sbtest8 |
| sbtest9 |
+------------------+
32 rows in set (0.00 sec)
Nu skal vi tage en backup. Der er flere måder, hvorpå vi kan gribe dette problem an. Vi kan bare tage en konsekvent backup af hele datasættet, men dette vil generere en stor, enkelt fil med alle dataene. For at gendanne den enkelte tabel skal vi udtrække data til tabellen fra den fil. Det er selvfølgelig muligt, men det er ret tidskrævende, og det er stort set manuel betjening, der kan scriptes, men hvis du ikke har ordentlige scripts på plads, er det at skrive ad hoc-kode, når din database er nede, og du er under hårdt pres. ikke nødvendigvis den sikreste idé.
I stedet for det kan vi forberede backup på en måde, så hver tabel bliver gemt i en separat fil:
[email protected]:~/backup# d=$(date +%Y%m%d) ; db='sbtest'; for tab in $(mysql -uroot -ppass -h127.0.0.1 -e "SHOW TABLES FROM ${db}" | grep -v Tables_in_${db}) ; do mysqldump --set-gtid-purged=OFF --routines --events --triggers ${db} ${tab} > ${d}_${db}.${tab}.sql ; done
Bemærk venligst, at vi indstiller --set-gtid-purged=OFF. Vi har brug for det, hvis vi senere indlæser disse data til databasen. Ellers vil MySQL forsøge at indstille @@GLOBAL.GTID_PURGED, hvilket højst sandsynligt vil mislykkes. MySQL ville lige så godt sætte SET @@SESSION.SQL_LOG_BIN=0; hvilket bestemt ikke er det vi ønsker. Disse indstillinger er nødvendige, hvis vi vil lave en ensartet sikkerhedskopi af hele datasættet, og vi gerne vil bruge det til at klargøre en ny node. I vores tilfælde ved vi, at det ikke er en konsekvent backup, og der er ingen måde, vi kan genopbygge noget fra det. Det eneste, vi ønsker, er at generere et dump, som vi kan indlæse på masteren og lade det replikere til slaver.
Denne kommando genererede en god liste over sql-filer, der kan uploades til produktionsklyngen:
[email protected]:~/backup# ls -alh
total 605M
drwxr-xr-x 2 root root 4.0K Mar 18 14:10 .
drwx------ 9 root root 4.0K Mar 18 14:08 ..
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest10.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest11.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest12.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest13.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest14.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest15.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest16.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest17.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest18.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest19.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest1.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest20.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest21.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest22.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest23.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest24.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest25.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest26.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest27.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest28.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest29.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest2.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest30.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest31.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest32.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest3.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest4.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest5.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest6.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest7.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest8.sql
-rw-r--r-- 1 root root 19M Mar 18 14:10 20200318_sbtest.sbtest9.sql
Når du gerne vil gendanne dataene, skal du blot indlæse SQL-filen i masternoden:
[email protected]:~/backup# mysql -uroot -ppass sbtest < 20200318_sbtest.sbtest11.sql
Data vil blive indlæst i databasen og replikeret til alle slaverne.
Hvordan gendannes en enkelt MySQL-tabel ved hjælp af ClusterControl?
I øjeblikket giver ClusterControl ikke en nem måde at gendanne kun en enkelt tabel, men det er stadig muligt at gøre det med nogle få manuelle handlinger. Der er to muligheder, du kan bruge. For det første, egnet til et lille antal tabeller, kan du grundlæggende oprette en tidsplan, hvor du udfører delvise sikkerhedskopier af en separat tabel én efter én:
Her tager vi en sikkerhedskopi af tabellen sbtest.sbtest1. Vi kan nemt planlægge endnu en backup til sbtest2 table:
Alternativt kan vi udføre en sikkerhedskopi og lægge data fra et enkelt skema ind i et separat fil:
Nu kan du enten finde de manglende data manuelt i filen, gendan denne backup til en separat server eller lad ClusterControl gøre det:
Du holder serveren oppe og køre, og du kan udtrække de data, du ønskede at gendanne med enten mysqldump eller SELECT ... INTO OUTFILE. Sådanne udtrukne data vil være klar til at blive anvendt på produktionsklyngen.