MySQL-slaves kunnen inconsistent worden. Je kunt het proberen te vermijden, maar het is echt moeilijk. Het instellen van super_read_only en het gebruik van op rijen gebaseerde replicatie kan veel helpen, maar wat je ook doet, het is nog steeds mogelijk dat je slaaf inconsistent wordt.
Wat kan er worden gedaan om een inconsistente MySQL-slave opnieuw op te bouwen? In deze blogpost bekijken we dit probleem.
Laten we eerst bespreken wat er moet gebeuren om een slaaf weer op te bouwen. Om een knooppunt in MySQL-replicatie te brengen, moet het worden voorzien van gegevens van een van de knooppunten in de replicatietopologie. Deze gegevens moeten consistent zijn op het moment waarop ze zijn verzameld. U kunt het niet per tabel of schema per schema bekijken, omdat hierdoor het ingerichte knooppunt intern inconsistent wordt. Dit betekent dat sommige gegevens ouder zijn dan een ander deel van de gegevensset.
Naast gegevensconsistentie moet het ook mogelijk zijn om informatie te verzamelen over de relatie tussen de gegevens en de replicatiestatus. U wilt een binaire logpositie hebben waarop de verzamelde gegevens consistent zijn, of een globale transactie-ID van de transactie die als laatste is uitgevoerd op het knooppunt dat de bron van de gegevens is.
Dit brengt ons bij de volgende overwegingen. U kunt een slave opnieuw opbouwen met elke back-uptool, zolang deze tool maar consistente back-up kan genereren en replicatiecoördinaten bevat voor het tijdstip waarop de back-up consistent is. Hierdoor kunnen we uit een aantal opties kiezen.
Mysqldump gebruiken om een inconsistente MySQL-slave opnieuw op te bouwen
Mysqldump is de meest elementaire tool die we hebben om dit te bereiken. Hiermee kunnen we een logische back-up maken in onder andere de vorm van SQL-statements. Wat belangrijk is, hoewel het eenvoudig is, stelt het ons toch in staat om een consistente back-up te maken:het kan transactie gebruiken om ervoor te zorgen dat de gegevens consistent zijn aan het begin van de transactie. Het kan ook replicatiecoördinaten voor dat punt noteren, zelfs een hele CHANGE MASTER-instructie, waardoor het gemakkelijk wordt om de replicatie te starten met behulp van de back-up.
Mydumper gebruiken om een inconsistente MySQL-slave opnieuw op te bouwen
Een andere optie is om mydumper te gebruiken - deze tool genereert, net als mysqldump, een logische back-up en kan, net als mysqldump, worden gebruikt om een consistente back-up van de database te maken. Het belangrijkste verschil tussen mydumper en mysqldump is dat mydumper, in combinatie met myloader, gegevens parallel kan dumpen en herstellen, waardoor de dump wordt verbeterd en vooral de hersteltijd.
Een momentopname gebruiken om een inconsistente MySQL-slave opnieuw op te bouwen
Voor degenen die cloudproviders gebruiken, is een mogelijkheid om een momentopname te maken van de onderliggende blokopslag. Snapshots genereren een point-in-time weergave van de gegevens. Dit proces is echter behoorlijk lastig, omdat de consistentie van de gegevens en de mogelijkheid om deze te herstellen grotendeels afhangt van de MySQL-configuratie.
Je moet ervoor zorgen dat de database in een duurzame modus werkt (deze is zo geconfigureerd dat het crashen van de MySQL niet leidt tot gegevensverlies). Dit komt omdat (vanuit een MySQL-standpunt) het nemen van een volume-snapshot en het starten van een ander MySQL-exemplaar van de daarin opgeslagen gegevens in feite hetzelfde proces is als wanneer je -9 de mysqld zou doden en het dan opnieuw zou starten. Het InnoDB-herstel moet plaatsvinden, transacties die zijn opgeslagen in binaire logboeken opnieuw afspelen, transacties terugdraaien die niet zijn voltooid vóór de crash, enzovoort.
Het nadeel van een op snapshots gebaseerd herbouwproces is dat het sterk gebonden is aan de huidige leverancier. U kunt de snapshotgegevens niet gemakkelijk kopiëren van de ene cloudprovider naar de andere. Je kunt het misschien tussen verschillende regio's verplaatsen, maar het blijft dezelfde provider.
Een Xtrabackup of Mariabackup gebruiken om een inconsistente MySQL-slave opnieuw op te bouwen
Tot slot, xtrabackup/mariabackup - dit is een tool geschreven door Percona en ontwikkeld door MariaDB waarmee een fysieke back-up kan worden gegenereerd. Het is veel sneller dan logische back-ups - het wordt meestal beperkt door de hardwareprestaties - schijf of netwerk zijn de meest waarschijnlijke knelpunten. De meeste werklast is gerelateerd aan het kopiëren van bestanden van de MySQL-gegevensmap naar een andere locatie (op dezelfde host of via het netwerk).
Hoewel lang niet zo snel als snapshots van blokopslag, is xtrabackup veel flexibeler en kan het in elke omgeving worden gebruikt. De back-up die het maakt, bestaat uit bestanden, daarom is het perfect mogelijk om de back-up naar elke gewenste locatie te kopiëren. Een andere cloudprovider, uw lokale datacenter, het maakt niet uit, zolang u maar bestanden kunt overzetten vanaf uw huidige locatie.
Het hoeft niet eens een netwerkverbinding te hebben - je kunt de back-up net zo goed kopiëren naar een "overdraagbaar" apparaat zoals een USB SSD of zelfs een USB-stick, zolang het maar alle gegevens en bewaar deze in uw zak terwijl u van het ene datacenter naar het andere verhuist.
Hoe een MySQL-slave opnieuw op te bouwen met Xtrabackup?
We hebben besloten ons te concentreren op xtrabackup, gezien de flexibiliteit en het vermogen om te werken in de meeste omgevingen waar MySQL kan bestaan. Hoe herbouw je je slave met xtrabackup? Laten we eens kijken.
Aanvankelijk hebben we een master en een slave, die last hadden van enkele replicatieproblemen:
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.141
Master_User: rpl_user
Master_Port: 3306
Connect_Retry: 10
Master_Log_File: binlog.000004
Read_Master_Log_Pos: 386
Relay_Log_File: relay-bin.000008
Relay_Log_Pos: 363
Relay_Master_Log_File: binlog.000004
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 1007
Last_Error: Error 'Can't create database 'mytest'; database exists' on query. Default database: 'mytest'. Query: 'create database mytest'
Skip_Counter: 0
Exec_Master_Log_Pos: 195
Relay_Log_Space: 756
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 1007
Last_SQL_Error: Error 'Can't create database 'mytest'; database exists' on query. Default database: 'mytest'. Query: 'create database mytest'
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1001
Master_UUID: 53d96192-53f7-11ea-9c3c-080027c5bc64
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State:
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp: 200306 11:47:42
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set: 53d96192-53f7-11ea-9c3c-080027c5bc64:9
Executed_Gtid_Set: 53d96192-53f7-11ea-9c3c-080027c5bc64:1-8,
ce7d0c38-53f7-11ea-9f16-080027c5bc64:1-3
Auto_Position: 1
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
1 row in set (0.00 sec)
Zoals je kunt zien, is er een probleem met een van de schema's. Laten we aannemen dat we dit knooppunt opnieuw moeten opbouwen om het terug te brengen in de replicatie. Dit zijn de stappen die we moeten uitvoeren.
Eerst moeten we ervoor zorgen dat xtrabackup is geïnstalleerd. In ons geval gebruiken we MySQL 8.0, daarom moeten we xtrabackup in versie 8 gebruiken om compatibiliteit te garanderen:
[email protected]:~# apt install percona-xtrabackup-80
Reading package lists... Done
Building dependency tree
Reading state information... Done
percona-xtrabackup-80 is already the newest version (8.0.9-1.bionic).
0 upgraded, 0 newly installed, 0 to remove and 143 not upgraded.
Xtrabackup wordt geleverd door de Percona-repository en de installatiehandleiding vindt u hier:
https://www.percona.com/doc/percona-xtrabackup/8.0/installation/apt_repo.html
De tool moet worden geïnstalleerd op zowel de master als de slave die we willen herbouwen.
Als volgende stap zullen we alle gegevens van de "kapotte" slave verwijderen:
[email protected]:~# service mysql stop
[email protected]:~# rm -rf /var/lib/mysql/*
Vervolgens nemen we de back-up op de master en streamen deze naar de slave. Houd er rekening mee dat deze specifieke one-liner een wachtwoordloze SSH-rootverbinding vereist van de master naar de slave:
[email protected]:~# xtrabackup --backup --compress --stream=xbstream --target-dir=./ | ssh [email protected] "xbstream -x --decompress -C /var/lib/mysql/"
Aan het einde zou je een belangrijke regel moeten zien:
200306 12:10:40 completed OK!
Dit is een indicatie dat de back-up in orde is gemaakt. Er kunnen nog steeds een paar dingen mis gaan, maar we hebben in ieder geval de gegevens goed. Vervolgens moeten we op de slave de back-up voorbereiden.
[email protected]:~# xtrabackup --prepare --target-dir=/var/lib/mysql/
.
.
.
200306 12:16:07 completed OK!
Je zou opnieuw moeten zien dat het proces goed is voltooid. Misschien wilt u de gegevens nu terug kopiëren naar de MySQL-gegevensdirectory. Dat hoeven we niet te doen, omdat we de streamingback-up rechtstreeks in /var/lib/mysql hebben opgeslagen. Wat we echter willen doen, is ervoor zorgen dat de bestanden correct eigendom zijn:
[email protected]:~# chown -R mysql.mysql /var/lib/mysql
Laten we nu de GTID-coördinaten van de back-up controleren. We zullen ze later gebruiken bij het opzetten van de replicatie.
[email protected]:~# cat /var/lib/mysql/xtrabackup_binlog_info
binlog.000007 195 53d96192-53f7-11ea-9c3c-080027c5bc64:1-9
Ok, alles lijkt goed te zijn, laten we MySQL starten en doorgaan met het configureren van de replicatie:
[email protected]:~# service mysql start
[email protected]:~# mysql -ppass
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.18-9 Percona Server (GPL), Release '9', Revision '53e606f'
Copyright (c) 2009-2019 Percona LLC and/or its affiliates
Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
Nu moeten we de gtid_purged instellen op de GTID-set die we in de back-up hebben gevonden. Dat zijn GTID's die zijn "gedekt" door onze back-up. Alleen een nieuwe GTID mag worden gerepliceerd van de master.
mysql> SET GLOBAL gtid_purged='53d96192-53f7-11ea-9c3c-080027c5bc64:1-9';
Query OK, 0 rows affected (0.00 sec)
Now we can start the replication:
mysql> CHANGE MASTER TO MASTER_HOST='10.0.0.141', MASTER_USER='rpl_user', MASTER_PASSWORD='yIPpgNE4KE', MASTER_AUTO_POSITION=1;
Query OK, 0 rows affected, 2 warnings (0.02 sec)
mysql> START SLAVE;
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.0.0.141
Master_User: rpl_user
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: binlog.000007
Read_Master_Log_Pos: 380
Relay_Log_File: relay-bin.000002
Relay_Log_Pos: 548
Relay_Master_Log_File: binlog.000007
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 380
Relay_Log_Space: 750
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1001
Master_UUID: 53d96192-53f7-11ea-9c3c-080027c5bc64
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set: 53d96192-53f7-11ea-9c3c-080027c5bc64:10
Executed_Gtid_Set: 53d96192-53f7-11ea-9c3c-080027c5bc64:1-10
Auto_Position: 1
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Master_public_key_path:
Get_master_public_key: 0
Network_Namespace:
1 row in set (0.00 sec)
Zoals je kunt zien, repliceert onze slaaf van zijn meester.
Hoe een MySQL-slave opnieuw opbouwen met ClusterControl?
Als u een ClusterControl-gebruiker bent, kunt u in plaats van dit proces te doorlopen de slave in slechts een paar klikken opnieuw opbouwen. Aanvankelijk hebben we een duidelijk probleem met de replicatie:
Onze slave repliceert niet correct vanwege een fout.
Het enige wat we hoeven te doen is de taak "Rebuild Replication Slave" uitvoeren .
U krijgt een dialoogvenster te zien waarin u een hoofdknooppunt moet kiezen voor de slaaf die u wilt herbouwen. Klik vervolgens op Doorgaan en je bent helemaal klaar. ClusterControl zal de slave opnieuw opbouwen en de replicatie voor u instellen.
Kort, op basis van de grootte van de dataset, zou je werkende slave moeten zien:
Zoals u kunt zien, heeft ClusterControl met slechts een paar klikken de taak volbracht om de inconsistente replicatieslave opnieuw op te bouwen.