sql >> Database >  >> RDS >> Mysql

Hoe een inconsistente MySQL-slave opnieuw te bouwen?

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.


  1. node.js + mysql verbinding pooling

  2. Vergelijk arrays voor gelijkheid, negeer de volgorde van elementen

  3. Wat is het verschil tussen RANK en DENSE_RANK in SQL?

  4. Hoe kan ik een BEFORE-UPDATED-trigger doen met sql-server?