sql >> Database >  >> RDS >> MariaDB

Point-in-Time Recovery van MySQL- en MariaDB-gegevens uitvoeren met ClusterControl

Back-ups zijn cruciaal als het gaat om de veiligheid van gegevens. Ze zijn de ultieme oplossing voor noodherstel - u hebt geen bereikbare databaseknooppunten en uw datacenter had letterlijk in rook kunnen opgaan, maar zolang u een back-up van uw gegevens hebt, kunt u nog steeds herstellen van een dergelijke situatie.

Meestal gebruikt u back-ups om te herstellen van verschillende soorten gevallen:

  • toevallige DROP TABLE of DELETE zonder een WHERE-clausule, of met een WHERE-clausule die niet specifiek genoeg was.
  • een database-upgrade die mislukt en de gegevens corrumpeert
  • storing/corruptie van opslagmedia

Is terugzetten vanaf een back-up niet voldoende? Wat moet het op een bepaald moment zijn? We moeten er rekening mee houden dat een back-up een momentopname is van gegevens die op een bepaald moment zijn gemaakt. Als u om 01:00 uur een back-up maakt en er is per ongeluk om 11:00 uur een tafel verwijderd, dan kunt u uw gegevens tot 01:00 uur herstellen, maar hoe zit het met wijzigingen die tussen 01:00 en 11:00 uur zijn gebeurd? Die wijzigingen gaan verloren, tenzij u tussentijdse wijzigingen opnieuw kunt afspelen. Gelukkig heeft MySQL zo'n mechanisme voor het opslaan van wijzigingen - binaire logs. U weet misschien dat deze logs worden gebruikt voor replicatie - MySQL gebruikt ze om alle wijzigingen op te slaan die op de master zijn gebeurd, en een slave gebruikt ze om die wijzigingen opnieuw af te spelen en toe te passen op zijn dataset. Omdat de binlogs alle wijzigingen opslaan, kunt u ze ook gebruiken om verkeer opnieuw af te spelen. In deze blogpost bekijken we hoe ClusterControl u kan helpen bij het uitvoeren van Point-In-Time Recovery (PITR).

Back-up maken die compatibel is met Point-In-Time Recovery

Laten we het eerst hebben over de voorwaarden. Een host waar u back-ups van maakt, moet binaire logboeken hebben ingeschakeld. Zonder hen is PITR niet mogelijk. Tweede vereiste - een host waar u back-ups van maakt, moet alle binaire logboeken hebben die nodig zijn om naar een bepaald tijdstip te kunnen herstellen. Als u een te agressieve binaire logrotatie gebruikt, kan dit een probleem worden.

Laten we dus eens kijken hoe we deze functie in ClusterControl kunnen gebruiken. Allereerst moet u een back-up maken die compatibel is met PITR. Een dergelijke back-up moet volledig, volledig en consistent zijn. Voor xtrabackup geldt dat het PITR-compatibel is, zolang het een volledige dataset bevat (je hebt niet alleen een subset van schema's toegevoegd).

Voor mysqldump is er een optie om het PITR-compatibel te maken. Als u deze optie inschakelt, worden alle benodigde opties geconfigureerd (u kunt bijvoorbeeld geen afzonderlijke schema's kiezen om op te nemen in de dump) en wordt een back-up gemarkeerd als beschikbaar voor herstel op een bepaald tijdstip.

Point-in-Time herstel vanaf een back-up

Eerst moet je een back-up kiezen om te herstellen.

Als de back-up compatibel is met PITR, wordt een optie gepresenteerd om een ​​Point-In-Time Recovery uit te voeren. U hebt daarvoor twee opties:"Time Based" en "Position Based". Laten we het verschil tussen die twee opties bespreken.

“Tijdsgebaseerd” PITR

Met deze optie kunt u een datum en tijd doorgeven, tot wanneer de back-up moet worden hersteld. Het kan worden gedefinieerd binnen een resolutie van één seconde. Het garandeert niet dat alle gegevens worden hersteld, want zelfs als u de tijd heel precies definieert, kunnen er gedurende één seconde meerdere gebeurtenissen in het binaire logboek worden vastgelegd. Stel dat u weet dat het gegevensverlies plaatsvond op 18 april, om 10:00:01 uur. U geeft de volgende datum en tijd door aan het formulier:‘2018-04-18 10:00:00’. Houd er rekening mee dat u een tijd moet gebruiken die is gebaseerd op de tijdzone-instellingen op de databaseserver waarop de back-up is gemaakt.

Het kan nog steeds gebeuren dat het gegevensverlies niet eens de eerste was die plaatsvond om 10:00:01, dus sommige gebeurtenissen zullen tijdens het proces verloren gaan. Laten we eens kijken wat dat betekent.

Gedurende één seconde kunnen meerdere gebeurtenissen worden vastgelegd in binlogs. Laten we een dergelijk geval bekijken:
10:00:00 - gebeurtenissen A,B,C,D,E,F
10:00:01 - gebeurtenissen V,W,X,Y,Z
waarbij X de gebeurtenis voor gegevensverlies is. Met een granulariteit van een seconde kun je alles herstellen wat er om 10:00:00 (dus tot F) of tot 10:00:01 (tot Z) is gebeurd. Het laatste geval heeft geen zin omdat X opnieuw zou worden uitgevoerd. In het eerste geval missen we V en W.

Daarom is position based restore nauwkeuriger. U kunt zeggen "Ik wil herstellen tot W".

Op tijd gebaseerd herstel is het meest nauwkeurige dat u kunt krijgen zonder naar de binaire logboeken te gaan en de exacte positie te definiëren naar waar u wilt herstellen. Dit leidt ons naar de tweede methode om PITR te doen.

“Positiegebaseerd” PITR

Hier is enige ervaring met opdrachtregelprogramma's voor MySQL, namelijk het hulpprogramma mysqlbinlog, vereist. Aan de andere kant heb je de beste controle over hoe het herstel zal plaatsvinden.

Laten we een eenvoudig voorbeeld doornemen. Zoals u kunt zien in de bovenstaande schermafbeelding, moet u een binaire lognaam en binaire logpositie doorgeven tot welk punt de back-up moet worden hersteld. Meestal zou dit de laatste positie moeten zijn vóór het gegevensverlies.

Iemand voerde een SQL-opdracht uit die resulteerde in ernstig gegevensverlies:

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

Onze applicatie begon meteen te klagen:

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

We hebben een back-up, maar we willen alle gegevens tot op dat fatale moment herstellen. Allereerst gaan we ervan uit dat de applicatie niet werkt, dus we kunnen alle schrijfbewerkingen die na de DROP TABLE plaatsvonden als niet-belangrijk weggooien. Als uw toepassing tot op zekere hoogte werkt, moet u de resterende wijzigingen later samenvoegen. Oké, laten we de binaire logboeken eens bekijken om de positie van de DROP TABLE-instructie te vinden. Omdat we willen voorkomen dat alle binaire logboeken worden geparseerd, gaan we kijken wat de positie was die onze laatste back-up dekte. U kunt dat controleren door logboeken voor de nieuwste back-upset te bekijken en een regel te zoeken die lijkt op deze:

We hebben het dus over bestandsnaam 'binlog.000008' en positie '16184120'. Laten we dit als ons uitgangspunt gebruiken. Laten we eens kijken welke binaire logbestanden we hebben:

[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

Dus naast 'binlog.000008' hebben we ook 'binlog.000009' om te onderzoeken. Laten we de opdracht uitvoeren die binaire logboeken naar SQL-indeling converteert vanaf de positie die we in het back-uplogboek hebben gevonden:

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

Node '--verbose' is vereist om op rijen gebaseerde gebeurtenissen te decoderen. Dit is niet per se vereist voor de DROP TABLE waarnaar we op zoek zijn, maar voor andere soorten evenementen kan het nodig zijn.

Laten we in onze uitvoer zoeken naar de DROP TABLE-query:

[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 */
/*!*/;

In dit voorbeeld kunnen we twee gebeurtenissen zien. Ten eerste, op de positie van 20885489, wordt de GTID_NEXT variabele ingesteld.

# 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'/*!*/;

Ten tweede, op de positie van 20885554 is ons DROP TABLE-evenement. Dit leidt tot de conclusie dat we de PITR moeten uitvoeren tot de positie van 20885489. De enige vraag die moet worden beantwoord, is over welk binair logboek we het hebben. We kunnen dat controleren door te zoeken naar binlog-rotatie-items:

[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

Zoals duidelijk kan worden gezien door datums te vergelijken, is de rotatie naar binlog.000009 later gebeurd, daarom willen we binlog.000008 doorgeven als het binlog-bestand in het formulier.

Vervolgens moeten we beslissen of we de back-up op het cluster gaan herstellen of dat we een externe server willen gebruiken om deze te herstellen. Deze tweede optie kan handig zijn als u slechts een subset van gegevens wilt herstellen. U kunt de volledige fysieke back-up op een aparte host herstellen en vervolgens mysqldump gebruiken om de ontbrekende gegevens te dumpen en op de productieserver te laden.

Houd er rekening mee dat wanneer u de back-up op uw cluster herstelt, u andere knooppunten moet opnieuw opbouwen dan degene die u hebt hersteld. In het master-slave-scenario wil je normaal gesproken de back-up op de master herstellen en vervolgens de slaves ervan opnieuw opbouwen.

Als laatste stap ziet u een samenvatting van de acties die ClusterControl zal ondernemen.

Nadat de back-up is hersteld, zullen we ten slotte testen of de ontbrekende tabel is hersteld of niet:

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

Alles lijkt in orde, we zijn erin geslaagd om ontbrekende gegevens te herstellen.

De laatste stap die we moeten nemen is om onze slaaf weer op te bouwen. Houd er rekening mee dat er een optie is om een ​​PITR-back-up te gebruiken. In het voorbeeld hier is dit niet mogelijk omdat de slave de DROP TABLE-gebeurtenis zou repliceren en het uiteindelijk niet consistent zou zijn met de master.


  1. Hoe COERCIBILITY() werkt in MariaDB

  2. INSERT gebruiken met een PostgreSQL-database met Python

  3. Oracle-uitvoerparameters retourneren vanuit een opgeslagen procedure in .NET

  4. Welk datatype moet worden gebruikt voor het opslaan van telefoonnummers in SQL Server 2005?