sql >> Database teknologi >  >> RDS >> MariaDB

Sådan laver du punkt-i-tidsgendannelse af MySQL- og MariaDB-data ved hjælp af ClusterControl

Sikkerhedskopier er afgørende, når det kommer til datasikkerhed. De er den ultimative disaster recovery-løsning - du har ingen databasenoder, du kan nå, og dit datacenter kunne bogstaveligt talt være gået op i røg, men så længe du har en sikkerhedskopi af dine data, kan du stadig komme dig fra en sådan situation.

Typisk vil du bruge sikkerhedskopier til at gendanne fra forskellige typer sager:

  • utilsigtet DROP TABLE eller DELETE uden en WHERE-sætning, eller med en WHERE-sætning, der ikke var specifik nok.
  • en databaseopgradering, der fejler og ødelægger dataene
  • lagermediefejl/korruption

Er gendannelse fra backup ikke nok? Hvad skal det være point-in-time? Vi skal huske på, at en sikkerhedskopi er et øjebliksbillede af data taget på et givet tidspunkt. Hvis du tager en sikkerhedskopi kl. 01:00, og et bord blev fjernet ved et uheld kl. 11:00, kan du gendanne dine data op til kl. 01:00, men hvad med ændringer, der skete mellem kl. 01:00 og 11:00? Disse ændringer ville gå tabt, medmindre du kan afspille ændringer, der skete i mellemtiden. Heldigvis har MySQL en sådan mekanisme til lagring af ændringer - binære logfiler. Du ved måske, at disse logfiler bruges til replikering - MySQL bruger dem til at gemme alle de ændringer, der skete på masteren, og en slave bruger dem til at afspille disse ændringer og anvende dem på sit datasæt. Da binlogs gemmer alle ændringerne, kan du også bruge dem til at afspille trafik igen. I dette blogindlæg vil vi tage et kig på, hvordan ClusterControl kan hjælpe dig med at udføre Point-In-Time Recovery (PITR).

Oprettelse af sikkerhedskopiering, der er kompatibel med punkt-i-tidsgendannelse

Først og fremmest, lad os tale om forudsætninger. En vært, hvor du tager sikkerhedskopier fra, skal have binære logfiler aktiveret. Uden dem er PITR ikke muligt. Andet krav - en vært, hvorfra du tager sikkerhedskopier, skal have alle de binære logfiler, der kræves for at gendanne til et givet tidspunkt. Hvis du bruger for aggressiv binær log-rotation, kan dette blive et problem.

Så lad os se, hvordan man bruger denne funktion i ClusterControl. Først og fremmest skal du tage en sikkerhedskopi, som er kompatibel med PITR. Sådan sikkerhedskopiering skal være fuld, fuldstændig og konsekvent. For xtrabackup vil det være PITR-kompatibelt, så længe det indeholder fuldt datasæt (du inkluderede ikke kun et undersæt af skemaer).

For mysqldump er der en mulighed for at gøre den PITR-kompatibel. Når du aktiverer denne indstilling, konfigureres alle nødvendige indstillinger (f.eks. vil du ikke være i stand til at vælge separate skemaer, der skal inkluderes i dumpet), og backup vil blive markeret som tilgængelig for gendannelse på tidspunktet.

Punkt-i-tids-gendannelse fra en sikkerhedskopi

Først skal du vælge en sikkerhedskopi for at gendanne.

Hvis sikkerhedskopien er kompatibel med PITR, vil der blive vist en mulighed for at udføre en punkt-i-tidsgendannelse. Du vil have to muligheder for det - "Tidsbaseret" og "Positionsbaseret". Lad os diskutere forskellen mellem disse to muligheder.

"Tidsbaseret" PITR

Med denne mulighed kan du sende en dato og et klokkeslæt, hvortil sikkerhedskopien skal gendannes. Det kan defineres inden for et sekunds opløsning. Det garanterer ikke, at alle data vil blive gendannet, fordi selvom du er meget præcis i at definere tiden, kan der i løbet af et sekund registreres flere hændelser i den binære log. Lad os sige, at du ved, at datatabet skete den 18. april kl. 10:00:01. Du sender følgende dato og klokkeslæt til formularen:‘2018-04-18 10:00:00’. Husk, at du skal bruge et klokkeslæt, der er baseret på tidszoneindstillingerne på databaseserveren, hvor sikkerhedskopien blev oprettet.

Det kan stadig ske, at datatabet endda ikke var det første, der skete kl. 10:00:01, så nogle af begivenhederne vil gå tabt i processen. Lad os se på, hvad det betyder.

I løbet af et sekund kan flere hændelser logges i binlogs. Lad os overveje sådanne tilfælde:
10:00:00 - begivenheder A,B,C,D,E,F
10:00:01 - begivenheder V,W,X,Y,Z
hvor X er datatabshændelsen. Med en granularitet på et sekund kan du enten gendanne op til alt, hvad der skete kl. 10:00:00 (altså op til F) eller op til 10:00:01 (op til Z). Det senere tilfælde er til ingen nytte, da X ville blive genudført. I førstnævnte tilfælde savner vi V og W.

Det er derfor, positionsbaseret gendannelse er mere præcis. Du kan fortælle "Jeg vil gendanne op til W".

Tidsbaseret gendannelse er den mest præcise, du kan få uden at skulle gå til de binære logfiler og definere den nøjagtige position, hvor du vil gendanne. Dette fører os til den anden metode til at lave PITR.

“Positionsbaseret” PITR

Her kræves en vis erfaring med kommandolinjeværktøjer til MySQL, nemlig mysqlbinlog-værktøjet. På den anden side vil du have den bedste kontrol over, hvordan genoprettelsen vil blive foretaget.

Lad os gennemgå et simpelt eksempel. Som du kan se på skærmbilledet ovenfor, skal du videregive et binært lognavn og binær logposition, indtil det tidspunkt, sikkerhedskopien skal gendannes. Det meste af tiden bør dette være den sidste position før datatabshændelsen.

Nogen udførte en SQL-kommando, som resulterede i et alvorligt datatab:

mysql> DROP TABLE sbtest1;
Query OK, 0 rows affected (0.02 sec)

Vores ansøgning begyndte straks at klage:

sysbench 1.1.0-ecf1191 (using bundled LuaJIT 2.1.0-beta3)

Running the test with following options:
Number of threads: 2
Report intermediate results every 1 second(s)
Initializing random number generator from current time


Initializing worker threads...

Threads started!

FATAL: mysql_drv_query() returned error 1146 (Table 'sbtest.sbtest1' doesn't exist) for query 'DELETE FROM sbtest1 WHERE id=5038'
FATAL: `thread_run' function failed: /usr/local/share/sysbench/oltp_common.lua:490: SQL error, errno = 1146, state = '42S02': Table 'sbtest.sbtest1' doesn't exist

Vi har en sikkerhedskopi, men vi ønsker at gendanne alle data op til det fatale øjeblik. Først og fremmest antager vi, at applikationen ikke virker, så vi kan kassere alle de skrivninger, der skete efter DROP TABLE, som ikke-vigtige. Hvis din applikation virker til en vis grad, bliver du nødt til at flette de resterende ændringer senere. Ok, lad os undersøge de binære logfiler for at finde positionen af ​​DROP TABLE-sætningen. Da vi gerne vil undgå at parse alle de binære logfiler, lad os finde ud af, hvad var den position, vores seneste backup dækkede. Du kan kontrollere det ved at undersøge logfiler for det seneste sikkerhedskopieringssæt og se efter en linje, der ligner denne:

Så vi taler om filnavnet 'binlog.000008' og positionen '16184120'. Lad os bruge dette som udgangspunkt. Lad os tjekke, hvilke binære logfiler vi har:

[email protected]:~# ls -alh /var/lib/mysql/binlog.*
-rw-r----- 1 mysql mysql  58M Apr 17 08:31 /var/lib/mysql/binlog.000001
-rw-r----- 1 mysql mysql 116M Apr 17 08:59 /var/lib/mysql/binlog.000002
-rw-r----- 1 mysql mysql 379M Apr 17 09:30 /var/lib/mysql/binlog.000003
-rw-r----- 1 mysql mysql 344M Apr 17 10:54 /var/lib/mysql/binlog.000004
-rw-r----- 1 mysql mysql 892K Apr 17 10:56 /var/lib/mysql/binlog.000005
-rw-r----- 1 mysql mysql  74M Apr 17 11:03 /var/lib/mysql/binlog.000006
-rw-r----- 1 mysql mysql 5.2M Apr 17 11:06 /var/lib/mysql/binlog.000007
-rw-r----- 1 mysql mysql  21M Apr 18 11:35 /var/lib/mysql/binlog.000008
-rw-r----- 1 mysql mysql  59K Apr 18 11:35 /var/lib/mysql/binlog.000009
-rw-r----- 1 mysql mysql  144 Apr 18 11:35 /var/lib/mysql/binlog.index

Så ud over 'binlog.000008' har vi også 'binlog.000009' at undersøge. Lad os køre kommandoen, som vil konvertere binære logfiler til SQL-format fra den position, vi fandt i backuploggen:

[email protected]:~# mysqlbinlog --start-position='16184120' --verbose /var/lib/mysql/binlog.000008 /var/lib/mysql/binlog.000009 > binlog.out

Node '--verbose' er påkrævet for at afkode rækkebaserede hændelser. Dette er ikke nødvendigvis nødvendigt for den DROP TABLE, vi leder efter, men til andre typer begivenheder kan det være nødvendigt.

Lad os søge i vores output efter DROP TABLE-forespørgslen:

[email protected]:~# grep -B 7 -A 1 "DROP TABLE" binlog.out
# at 20885489
#180418 11:24:32 server id 1  end_log_pos 20885554 CRC32 0xb89f2e66     GTID    last_committed=38168    sequence_number=38170    rbr_only=no
SET @@SESSION.GTID_NEXT= '7fe29cb7-422f-11e8-b48d-0800274b240e:38170'/*!*/;
# at 20885554
#180418 11:24:32 server id 1  end_log_pos 20885678 CRC32 0xb38a427b     Query    thread_id=54    exec_time=0    error_code=0
use `sbtest`/*!*/;
SET TIMESTAMP=1524050672/*!*/;
DROP TABLE `sbtest1` /* generated by server */
/*!*/;

I dette eksempel kan vi se to begivenheder. Først, ved positionen 20885489, indstiller GTID_NEXT variabel.

# at 20885489
#180418 11:24:32 server id 1  end_log_pos 20885554 CRC32 0xb89f2e66     GTID    last_committed=38168    sequence_number=38170    rbr_only=no
SET @@SESSION.GTID_NEXT= '7fe29cb7-422f-11e8-b48d-0800274b240e:38170'/*!*/;

For det andet, på positionen 20885554 er vores DROP TABLE begivenhed. Dette fører til den konklusion, at vi skal udføre PITR op til positionen 20885489. Det eneste spørgsmål, der skal besvares, er, hvilken binær log vi taler om. Vi kan kontrollere det ved at søge efter binlog-rotationsposter:

[email protected]:~# grep  "Rotate to binlog" binlog.out
#180418 11:35:46 server id 1  end_log_pos 21013114 CRC32 0x2772cc18     Rotate to binlog.000009  pos: 4

Som det tydeligt kan ses ved at sammenligne datoer, skete rotation til binlog.000009 senere, derfor ønsker vi at videregive binlog.000008 som binlog-filen i formularen.

Dernæst skal vi beslutte, om vi skal gendanne sikkerhedskopien på klyngen, eller om vi vil bruge ekstern server til at gendanne den. Denne anden mulighed kan være nyttig, hvis du kun vil gendanne en delmængde af data. Du kan gendanne fuld fysisk backup på en separat vært og derefter bruge mysqldump til at dumpe de manglende data og indlæse dem på produktionsserveren.

Husk, at når du gendanner sikkerhedskopien på din klynge, bliver du nødt til at genopbygge andre noder end den, du gendannede. I master - slave scenarie vil du typisk ønske at gendanne backup på masteren og derefter genopbygge slaver fra den.

Som et sidste trin vil du se en oversigt over handlinger ClusterControl vil tage.

Til sidst, efter at sikkerhedskopien blev gendannet, vil vi teste, om den manglende tabel er blevet gendannet eller ej:

mysql> show tables from sbtest like 'sbtest1'\G
*************************** 1. row ***************************
Tables_in_sbtest (sbtest1): sbtest1
1 row in set (0.00 sec)

Alt ser ud til at være ok, det lykkedes os at gendanne manglende data.

Det sidste skridt, vi skal tage, er at genopbygge vores slave. Bemærk venligst, at der er mulighed for at bruge en PITR backup. I eksemplet her er dette ikke muligt, da slaven ville replikere DROP TABLE-hændelsen, og den ville ende med ikke at være i overensstemmelse med masteren.


  1. Sådan automatiseres udrulning af PostgreSQL-database

  2. Oracle SQL:tidsstempler i where-sætning

  3. Indsættelse af store objektdata i Salesforce.com fra SQL Server

  4. Bestemmelse af, om feltdataene i Oracle er af nummertypen