MySQL-slaver kan blive inkonsekvente. Du kan prøve at undgå det, men det er virkelig svært. At indstille super_read_only og bruge rækkebaseret replikering kan hjælpe meget, men uanset hvad du gør, er det stadig muligt, at din slave bliver inkonsekvent.
Hvad kan man gøre for at genopbygge en inkonsekvent MySQL-slave? I dette blogindlæg tager vi et kig på dette problem.
Først og fremmest, lad os diskutere, hvad der skal ske for at genopbygge en slave. For at bringe en node ind i MySQL-replikering skal den forsynes med data fra en af noderne i replikeringstopologien. Disse data skal være konsistente på det tidspunkt, hvor de blev indsamlet. Du kan ikke tage det på en tabel for tabel eller skema for skema, fordi dette vil gøre den klargjorte node inkonsekvent internt. Det betyder, at nogle data ville være ældre end en anden del af datasættet.
Ud over datakonsistens bør det også være muligt at indsamle information om forholdet mellem dataene og replikationstilstanden. Du vil have enten binær logposition, hvor de indsamlede data er konsistente, eller Global Transaction ID for transaktionen, som var den sidst udførte på den node, der er kilden til dataene.
Dette fører os til følgende overvejelser. Du kan genopbygge en slave ved hjælp af ethvert sikkerhedskopieringsværktøj, så længe dette værktøj kan generere konsekvent sikkerhedskopiering, og det inkluderer replikeringskoordinater for det tidspunkt, hvor sikkerhedskopieringen er konsistent. Dette giver os mulighed for at vælge mellem et par muligheder.
Brug af Mysqldump til at genopbygge en inkonsekvent MySQL-slave
Mysqldump er det mest grundlæggende værktøj, vi har for at opnå dette. Det giver os mulighed for at lave en logisk backup i blandt andet form af SQL-sætninger. Hvad der er vigtigt, mens det er grundlæggende, giver det os stadig mulighed for at tage en konsekvent backup:den kan bruge transaktionen til at sikre, at dataene er konsistente i begyndelsen af transaktionen. Den kan også nedskrive replikeringskoordinater for det punkt, endda en hel CHANGE MASTER-sætning, hvilket gør det nemt at starte replikeringen ved hjælp af sikkerhedskopien.
Brug af Mydumper til at genopbygge en inkonsekvent MySQL-slave
En anden mulighed er at bruge mydumper - dette værktøj, ligesom mysqldump, genererer en logisk backup og kan, ligesom mysqldump, bruges til at lave en konsistent backup af databasen. Den største forskel mellem mydumper og mysqldump er, at mydumper, når den er parret med myloader, kan dumpe og gendanne data parallelt, hvilket forbedrer dumpen og især genskaber tiden.
Brug af et snapshot til at genopbygge en inkonsekvent MySQL-slave
For dem, der bruger cloud-udbydere, er en mulighed at tage et øjebliksbillede af den underliggende bloklagring. Snapshots genererer et punkt-i-tidsbillede af dataene. Denne proces er dog ret besværlig, da konsistensen af dataene og evnen til at gendanne dem afhænger for det meste af MySQL-konfigurationen.
Du bør sikre dig, at databasen fungerer i en holdbar tilstand (den er konfigureret på en måde, så nedbrud af MySQL ikke vil resultere i tab af data). Dette skyldes (fra et MySQL-synspunkt) at tage et volumen-øjebliksbillede og derefter starte en anden MySQL-instans fra de data, der er gemt i den, dybest set er den samme proces, som hvis du ville dræbe -9 mysqld'en og derefter starte den igen. InnoDB-gendannelsen skal ske, genafspil transaktioner, der er blevet gemt i binære logfiler, rollback-transaktioner, der ikke er gennemført før nedbruddet og så videre.
Ulempen ved snapshot-baseret genopbygningsproces er, at den er stærkt knyttet til den nuværende leverandør. Du kan ikke nemt kopiere snapshot-dataene fra en cloud-udbyder til en anden. Du kan muligvis flytte det mellem forskellige regioner, men det vil stadig være den samme udbyder.
Brug af en Xtrabackup eller Mariabackup til at genopbygge en inkonsekvent MySQL-slave
Til sidst, xtrabackup/mariabackup - dette er et værktøj skrevet af Percona og forgrenet af MariaDB, der gør det muligt at generere en fysisk backup. Det er langt hurtigere end logiske sikkerhedskopier - det er for det meste begrænset af hardwareydelsen - disk eller netværk er de mest sandsynlige flaskehalse. Det meste af arbejdsbyrden er relateret til kopiering af filer fra MySQL-datamappe til en anden placering (på samme vært eller over netværket).
Selv om det ikke er nær så hurtigt som snapshots af bloklagring, er xtrabackup meget mere fleksibelt og kan bruges i ethvert miljø. Sikkerhedskopien den producerer består af filer, derfor er det perfekt muligt at kopiere sikkerhedskopien til et hvilket som helst sted, du ønsker. En anden cloud-udbyder, dit lokale datacenter, det er ligegyldigt, så længe du kan overføre filer fra din nuværende placering.
Det behøver ikke engang at have netværksforbindelse - du kan lige så godt bare kopiere sikkerhedskopien til en "overførbar" enhed som USB SSD eller endda USB-stick, så længe den kan indeholde alle data og gem dem i lommen, mens du flytter fra et datacenter til et andet.
Hvordan genopbygger man en MySQL-slave ved hjælp af Xtrabackup?
Vi besluttede at fokusere på xtrabackup på grund af dets fleksibilitet og evne til at arbejde i de fleste af de miljøer, hvor MySQL kan eksistere. Hvordan genopbygger du din slave ved hjælp af xtrabackup? Lad os tage et kig.
I første omgang har vi en master og en slave, som led af nogle replikeringsproblemer:
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, er der et problem med et af skemaerne. Lad os antage, at vi skal genopbygge denne node for at bringe den tilbage i replikationen. Her er de trin, vi skal udføre.
Først skal vi sørge for, at xtrabackup er installeret. I vores tilfælde bruger vi MySQL 8.0, derfor er vi nødt til at bruge xtrabackup i version 8 for at sikre 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 leveres af Percona repository, og vejledningen til at installere det kan findes her:
https://www.percona.com/doc/percona-xtrabackup/8.0/installation/apt_repo.html
Værktøjet skal installeres på både master og slave, som vi ønsker at genopbygge.
Som et næste trin vil vi fjerne alle data fra den "brudte" slave:
[email protected]:~# service mysql stop
[email protected]:~# rm -rf /var/lib/mysql/*
Derefter tager vi backup'en på masteren og streamer den til slaven. Husk at denne særlige one-liner kræver adgangskodefri SSH-rodforbindelse fra masteren til slaven:
[email protected]:~# xtrabackup --backup --compress --stream=xbstream --target-dir=./ | ssh [email protected] "xbstream -x --decompress -C /var/lib/mysql/"
I slutningen skulle du se en vigtig linje:
200306 12:10:40 completed OK!
Dette er en indikator for, at sikkerhedskopieringen er fuldført OK. Et par ting kan stadig gå galt, men i det mindste fik vi dataene rigtige. Dernæst skal vi på slaven forberede sikkerhedskopien.
[email protected]:~# xtrabackup --prepare --target-dir=/var/lib/mysql/
.
.
.
200306 12:16:07 completed OK!
Du skulle igen kunne se, at processen fuldførte OK. Du vil måske nu kopiere dataene tilbage til MySQL-databiblioteket. Vi behøver ikke at gøre det, da vi gemte streaming backup direkte i /var/lib/mysql. Hvad vi dog ønsker at gøre, er at sikre korrekt ejerskab af filerne:
[email protected]:~# chown -R mysql.mysql /var/lib/mysql
Lad os nu tjekke GTID-koordinaterne for sikkerhedskopieringen. Vi vil bruge dem senere, når vi opsætter replikeringen.
[email protected]:~# cat /var/lib/mysql/xtrabackup_binlog_info
binlog.000007 195 53d96192-53f7-11ea-9c3c-080027c5bc64:1-9
Ok, alt ser ud til at være i orden, lad os starte MySQL og fortsætte med at konfigurere 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 skal vi indstille gtid_purged til det GTID-sæt, som vi fandt i sikkerhedskopien. Det er GTID, der er blevet "dækket" af vores backup. Kun nyt GTID bør replikeres fra masteren.
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, replikerer vores slave fra sin herre.
Hvordan genopbygger man en MySQL-slave ved hjælp af ClusterControl?
Hvis du er en ClusterControl-bruger, kan du i stedet for at gennemgå denne proces genopbygge slaven med blot et par klik. I første omgang har vi et klart problem med replikeringen:
Vores slave replikerer ikke korrekt på grund af en fejl.
Alt vi skal gøre er at køre "Rebuild Replication Slave"-jobbet .
Du vil blive præsenteret for en dialogboks, hvor du skal vælge en masterknude til slaven, som du vil genopbygge. Klik derefter på Fortsæt, og du er klar. ClusterControl vil genopbygge slaven og konfigurere replikeringen for dig.
I kort tid, baseret på datasættets størrelse, skulle du se en fungerende slave:
Som du kan se, udførte ClusterControl med blot et par klik opgaven med at genopbygge den inkonsekvente replikeringsslave.