sql >> Databasteknik >  >> RDS >> Mysql

Hur bygger man om en inkonsekvent MySQL-slav?

MySQL-slavar kan bli inkonsekventa. Du kan försöka undvika det, men det är verkligen svårt. Att ställa in super_read_only och använda radbaserad replikering kan hjälpa mycket, men oavsett vad du gör är det fortfarande möjligt att din slav blir inkonsekvent.

Vad kan göras för att återuppbygga en inkonsekvent MySQL-slav? I det här blogginlägget tar vi en titt på det här problemet.

Först och främst, låt oss diskutera vad som måste hända för att återuppbygga en slav. För att föra in en nod till MySQL-replikering måste den förses med data från en av noderna i replikeringstopologin. Dessa uppgifter måste vara konsekventa vid den tidpunkt då de samlades in. Du kan inte ta det på en tabell för tabell eller schema för schema, eftersom detta kommer att göra den tillhandahållna noden inkonsekvent internt. Det betyder att vissa data skulle vara äldre än någon annan del av datamängden.

Förutom datakonsistens bör det också vara möjligt att samla in information om förhållandet mellan data och replikeringstillstånd. Du vill ha antingen binär loggposition där den insamlade informationen är konsekvent eller globalt transaktions-ID för transaktionen som var den senast exekverade på noden som är källan till data.

Detta leder oss till följande överväganden. Du kan bygga om en slav med hjälp av vilket säkerhetskopieringsverktyg som helst så länge som detta verktyg kan generera konsekvent säkerhetskopiering och det inkluderar replikeringskoordinater för den tidpunkt då säkerhetskopieringen är konsekvent. Detta gör att vi kan välja mellan ett par alternativ.

Använda Mysqldump för att bygga om en inkonsekvent MySQL-slav

Mysqldump är det mest grundläggande verktyget vi har för att uppnå detta. Det gör att vi kan skapa en logisk backup i bland annat form av SQL-satser. Vad som är viktigt, samtidigt som det är grundläggande, tillåter det oss ändå att ta en konsekvent säkerhetskopia:den kan använda transaktionen för att säkerställa att data är konsekventa i början av transaktionen. Den kan också skriva ner replikeringskoordinater för den punkten, till och med en hel CHANGE MASTER-sats, vilket gör det enkelt att starta replikeringen med hjälp av säkerhetskopian.

Använda Mydumper för att bygga om en inkonsekvent MySQL-slav

Ett annat alternativ är att använda mydumper - detta verktyg, precis som mysqldump, genererar en logisk säkerhetskopia och kan, precis som mysqldump, användas för att skapa en konsekvent säkerhetskopia av databasen. Den största skillnaden mellan mydumper och mysqldump är att mydumper, när den är ihopkopplad med myloader, kan dumpa och återställa data parallellt, vilket förbättrar dumpningen och framför allt återställer tiden.

Använda en ögonblicksbild för att bygga om en inkonsekvent MySQL-slav

För de som använder molnleverantörer är en möjlighet att ta en ögonblicksbild av den underliggande blocklagringen. Ögonblicksbilder genererar en punkt-i-tidsvy av data. Denna process är dock ganska knepig, eftersom konsistensen av data och möjligheten att återställa den beror mest på MySQL-konfigurationen.

Du bör se till att databasen fungerar i ett hållbart läge (den är konfigurerad på ett sådant sätt att en krasch av MySQL inte kommer att resultera i någon dataförlust). Detta beror på att (ur MySQL-synpunkt) att ta en volymögonblicksbild och sedan starta en annan MySQL-instans från data som lagras i den är i princip samma process som om du skulle döda -9 mysqld och sedan starta den igen. InnoDB-återställningen måste ske, spela om transaktioner som har lagrats i binära loggar, återställningstransaktioner som inte har slutförts före kraschen och så vidare.

Nackdelen med en ögonblicksbildsbaserad ombyggnadsprocess är att den är starkt knuten till den nuvarande leverantören. Du kan inte enkelt kopiera ögonblicksbilddata från en molnleverantör till en annan. Du kanske kan flytta det mellan olika regioner men det kommer fortfarande att vara samma leverantör.

Använda en Xtrabackup eller Mariabackup för att bygga om en inkonsekvent MySQL-slav

Äntligen, xtrabackup/mariabackup - detta är ett verktyg skrivet av Percona och forked av MariaDB som gör det möjligt att skapa en fysisk säkerhetskopia. Det är mycket snabbare än logiska säkerhetskopieringar - det begränsas mestadels av hårdvarans prestanda - disk eller nätverk är de mest troliga flaskhalsarna. Det mesta av arbetsbelastningen är relaterad till kopiering av filer från MySQL-datakatalogen till en annan plats (på samma värd eller över nätverket).

Även om det inte alls är lika snabbt som ögonblicksbilder av blocklagring, är xtrabackup mycket mer flexibelt och kan användas i alla miljöer. Säkerhetskopieringen den producerar består av filer, därför är det fullt möjligt att kopiera säkerhetskopian till vilken plats du vill. En annan molnleverantör, ditt lokala datacenter, det spelar ingen roll så länge du kan överföra filer från din nuvarande plats.

Den behöver inte ens ha nätverksanslutning - du kan också bara kopiera säkerhetskopian till någon "överförbar" enhet som USB SSD eller till och med USB-minne, så länge den kan innehålla alla data och lagra den i fickan medan du flyttar från ett datacenter till ett annat.

Hur bygger man om en MySQL-slav med Xtrabackup?

Vi bestämde oss för att fokusera på xtrabackup, med tanke på dess flexibilitet och förmåga att arbeta i de flesta miljöer där MySQL kan existera. Hur bygger du om din slav med hjälp av xtrabackup? Låt oss ta en titt.

Initialt har vi en mästare och en slav, som led av några replikeringsproblem:

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)

Som du kan se är det ett problem med ett av schemana. Låt oss anta att vi måste bygga om den här noden för att föra tillbaka den till replikeringen. Här är stegen vi måste utföra.

Först måste vi se till att xtrabackup är installerat. I vårt fall använder vi MySQL 8.0 och därför måste vi använda xtrabackup i version 8 för att säkerställa kompatibilitet:

[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 tillhandahålls av Percona repository och guiden för att installera den finns här:

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

Verktyget måste installeras på både master och slav som vi vill bygga om.

Som ett nästa steg kommer vi att ta bort all data från den "trasiga" slaven:

[email protected]:~# service mysql stop

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

Närnäst tar vi säkerhetskopian på mastern och streamar den till slaven. Vänligen kom ihåg att just denna one-liner kräver lösenordslös SSH-rotanslutning från mastern till slaven:

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

I slutet bör du se en viktig rad:

200306 12:10:40 completed OK!

Detta är en indikator på att säkerhetskopieringen slutfördes OK. Ett par saker kan fortfarande gå fel men vi har åtminstone rätt information. Därefter, på slaven, måste vi förbereda säkerhetskopian.

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

.

.

.

200306 12:16:07 completed OK!

Du bör återigen se att processen slutfördes OK. Nu kanske du vill kopiera tillbaka data till MySQL-datakatalogen. Vi behöver inte göra det eftersom vi lagrade strömningsbackupen direkt i /var/lib/mysql. Vad vi dock vill göra är att säkerställa korrekt ägande av filerna:

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

Låt oss nu kontrollera GTID-koordinaterna för säkerhetskopieringen. Vi kommer att använda dem senare när vi ställer in replikeringen.

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

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

Ok, allt verkar vara bra, låt oss starta MySQL och fortsätta med att konfigurera replikeringen:

[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 måste vi ställa in gtid_purged till GTID-uppsättningen som vi hittade i säkerhetskopian. Det är GTID som har "täckts" av vår säkerhetskopia. Endast nytt GTID ska replikeras från mastern.

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)

Som du kan se replikerar vår slav från sin herre.

Hur bygger man om en MySQL-slav med ClusterControl?

Om du är en ClusterControl-användare kan du istället för att gå igenom den här processen bygga om slaven med bara ett par klick. Till en början har vi ett tydligt problem med replikeringen:

Vår slav replikerar inte ordentligt på grund av ett fel.

Allt vi behöver göra är att köra jobbet "Rebuild Replication Slave" .

Du kommer att presenteras med en dialogruta där du ska välja en huvudnod för slaven som du vill bygga om. Klicka sedan på Fortsätt och du är klar. ClusterControl kommer att bygga om slaven och ställa in replikeringen åt dig.

Inom kort tid, baserat på datamängdsstorleken, bör du se en fungerande slav:

Som du kan se, med bara ett par klick klarade ClusterControl uppgiften att återuppbygga den inkonsekventa replikeringsslaven.


  1. Hur man aktiverar/inaktiverar CHECK-begränsningar i SQLite

  2. 11 sätt att hitta dubbletter av rader som har en primärnyckel i Oracle

  3. Hur ROUND() fungerar i MariaDB

  4. Databasval för att skapa två sammankopplade tabeller?