Mysql
 sql >> Database >  >> RDS >> Mysql

Come ricostruire uno slave MySQL incoerente?

Gli slave MySQL potrebbero diventare incoerenti. Puoi provare a evitarlo, ma è davvero difficile. L'impostazione di super_read_only e l'utilizzo della replica basata su riga possono aiutare molto, ma qualunque cosa tu faccia, è comunque possibile che il tuo slave diventi incoerente.

Cosa si può fare per ricostruire uno slave MySQL incoerente? In questo post del blog daremo un'occhiata a questo problema.

Prima di tutto, discutiamo di cosa deve succedere per ricostruire uno schiavo. Per portare un nodo in MySQL Replication, deve essere fornito con i dati da uno dei nodi nella topologia di replica. Questi dati devono essere coerenti nel momento in cui sono stati raccolti. Non puoi prenderlo su una tabella per tabella o schema per schema, perché ciò renderà il nodo di cui è stato eseguito il provisioning incoerente internamente. Ciò significa che alcuni dati sarebbero più vecchi di altre parti del set di dati.

Oltre alla coerenza dei dati, dovrebbe anche essere possibile raccogliere informazioni sulla relazione tra i dati e lo stato di replica. Vuoi avere una posizione del log binario in cui i dati raccolti sono coerenti o l'ID transazione globale della transazione che è stata l'ultima eseguita sul nodo che è l'origine dei dati.

Questo ci porta alle seguenti considerazioni. È possibile ricostruire uno slave utilizzando qualsiasi strumento di backup purché questo strumento sia in grado di generare un backup coerente e includa le coordinate di replica per il momento in cui il backup è coerente. Questo ci consente di scegliere tra un paio di opzioni.

Utilizzo di Mysqldump per ricostruire uno slave MySQL incoerente

Mysqldump è lo strumento più basilare che abbiamo per raggiungere questo obiettivo. Ci consente di creare un backup logico, tra l'altro, sotto forma di istruzioni SQL. Ciò che è importante, pur essendo di base, ci consente comunque di eseguire un backup coerente:può utilizzare la transazione per garantire che i dati siano coerenti all'inizio della transazione. Può anche annotare le coordinate di replica per quel punto, anche un'intera istruzione CHANGE MASTER, facilitando l'avvio della replica utilizzando il backup.

Utilizzo di Mydumper per ricostruire uno slave MySQL incoerente

Un'altra opzione è usare mydumper:questo strumento, proprio come mysqldump, genera un backup logico e, proprio come mysqldump, può essere utilizzato per creare un backup coerente del database. La principale differenza tra mydumper e mysqldump è che mydumper, se associato a myloader, può eseguire il dump e il ripristino dei dati in parallelo, migliorando il dump e, soprattutto, il tempo di ripristino.

Utilizzo di uno snapshot per ricostruire uno slave MySQL incoerente

Per coloro che utilizzano provider cloud, una possibilità è quella di acquisire un'istantanea del block storage sottostante. Gli snapshot generano una vista puntuale dei dati. Tuttavia, questo processo è piuttosto complicato, poiché la consistenza dei dati e la capacità di ripristinarli dipendono principalmente dalla configurazione di MySQL.

Dovresti assicurarti che il database funzioni in una modalità durevole (è configurato in modo tale che il crash di MySQL non provochi alcuna perdita di dati). Questo perché (dal punto di vista di MySQL) acquisire un'istantanea del volume e quindi avviare un'altra istanza MySQL dai dati in essa archiviati è, fondamentalmente, lo stesso processo come se si uccidesse -9 mysqld e poi lo si riavviasse. Il ripristino di InnoDB deve avvenire, riprodurre le transazioni che sono state archiviate nei registri binari, le transazioni di rollback che non sono state completate prima dell'arresto anomalo e così via.

Lo svantaggio del processo di ricostruzione basato su snapshot è che è fortemente legato al fornitore attuale. Non è possibile copiare facilmente i dati delle istantanee da un provider cloud a un altro. Potresti essere in grado di spostarlo tra diverse regioni, ma sarà sempre lo stesso provider.

Utilizzo di Xtrabackup o Mariabackup per ricostruire uno slave MySQL incoerente

Infine, xtrabackup/mariabackup - questo è uno strumento scritto da Percona e forkato da MariaDB che permette di generare un backup fisico. È molto più veloce dei backup logici:è limitato principalmente dalle prestazioni hardware:disco o rete sono i colli di bottiglia più probabili. La maggior parte del carico di lavoro è correlata alla copia di file dalla directory dei dati di MySQL in un'altra posizione (sullo stesso host o sulla rete).

Anche se non è veloce quanto gli snapshot di archiviazione a blocchi, xtrabackup è molto più flessibile e può essere utilizzato in qualsiasi ambiente. Il backup che produce è costituito da file, quindi è perfettamente possibile copiare il backup in qualsiasi posizione desideri. Un altro fornitore di servizi cloud, il tuo datacenter locale, non importa fintanto che puoi trasferire file dalla tua posizione attuale.

Non deve nemmeno avere la connettività di rete:puoi anche copiare il backup su un dispositivo "trasferibile" come un SSD USB o persino una chiavetta USB, purché possa contenere tutti i dati e conservali in tasca mentre ti sposti da un datacenter all'altro.

Come ricostruire uno slave MySQL usando Xtrabackup?

Abbiamo deciso di concentrarci su xtrabackup, data la sua flessibilità e capacità di lavorare nella maggior parte degli ambienti in cui può esistere MySQL. Come ricostruisci il tuo slave usando xtrabackup? Diamo un'occhiata.

Inizialmente abbiamo un master e uno slave, che soffrivano di alcuni problemi di replica:

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)

Come puoi vedere, c'è un problema con uno degli schemi. Supponiamo di dover ricostruire questo nodo per riportarlo nella replica. Ecco i passaggi che dobbiamo eseguire.

Per prima cosa, dobbiamo assicurarci che xtrabackup sia installato. Nel nostro caso utilizziamo MySQL 8.0 quindi dobbiamo usare xtrabackup nella versione 8 per garantire la compatibilità:

[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 è fornito dal repository Percona e la guida per installarlo è disponibile qui:

https://www.percona.com/doc/percona-xtrabackup/8.0/installation/apt_repo.html

Lo strumento deve essere installato sia sul master che sullo slave che vogliamo ricostruire.

Come passaggio successivo rimuoveremo tutti i dati dallo slave "rotto":

[email protected]:~# service mysql stop

[email protected]:~# rm -rf /var/lib/mysql/*

Successivamente, prenderemo il backup sul master e lo trasmetteremo in streaming allo slave. Tieni presente che questo particolare one-liner richiede una connettività root SSH senza password dal master allo slave:

[email protected]:~# xtrabackup --backup --compress --stream=xbstream --target-dir=./ | ssh [email protected] "xbstream -x --decompress -C /var/lib/mysql/"

Alla fine dovresti vedere una riga importante:

200306 12:10:40 completed OK!

Questo è un indicatore che il backup è stato completato correttamente. Un paio di cose potrebbero ancora andare storte, ma almeno abbiamo i dati corretti. Successivamente, sullo slave, dobbiamo preparare il backup.

[email protected]:~# xtrabackup --prepare --target-dir=/var/lib/mysql/

.

.

.

200306 12:16:07 completed OK!

Dovresti vedere, ancora una volta, che il processo è stato completato correttamente. Potresti voler ora copiare nuovamente i dati nella directory dei dati di MySQL. Non è necessario farlo poiché abbiamo archiviato il backup in streaming direttamente in /var/lib/mysql. Quello che vogliamo fare, però, è garantire la corretta proprietà dei file:

[email protected]:~# chown -R mysql.mysql /var/lib/mysql

Ora controlliamo le coordinate GTID del backup. Li useremo in seguito durante l'impostazione della replica.

[email protected]:~# cat /var/lib/mysql/xtrabackup_binlog_info

binlog.000007 195 53d96192-53f7-11ea-9c3c-080027c5bc64:1-9

Ok, sembra tutto a posto, avviamo MySQL e procediamo con la configurazione della replica:

[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>

Ora dobbiamo impostare gtid_purged sul set GTID che abbiamo trovato nel backup. Quelli sono GTID che sono stati "coperti" dal nostro backup. Solo il nuovo GTID dovrebbe essere replicato dal 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)

Come puoi vedere, il nostro schiavo si sta replicando dal suo padrone.

Come ricostruire uno slave MySQL utilizzando ClusterControl?

Se sei un utente ClusterControl, invece di eseguire questo processo puoi ricostruire lo slave in un paio di clic. Inizialmente abbiamo un chiaro problema con la replica:

Il nostro slave non si replica correttamente a causa di un errore.

Tutto ciò che dobbiamo fare è eseguire il lavoro "Rebuild Replication Slave" .

Ti verrà presentata una finestra di dialogo in cui dovresti scegliere un nodo master per lo schiavo che vuoi ricostruire. Quindi, fai clic su Procedi e sei pronto. ClusterControl ricostruirà lo slave e imposterà la replica per te.

A breve, in base alla dimensione del set di dati, dovresti vedere lo slave funzionante:

Come puoi vedere, con solo un paio di clic ClusterControl ha eseguito il compito di ricostruire lo slave di replica incoerente.