Indholdsfortegnelse
Hvad er problemet?
Du har sikkert opdaget at din slave ikke længere replikerer ved at kigge på SHOW SLAVE STATUS, her et eksempel:
1 2 3 4 5 6 7 8 |
MariaDB> SHOW SLAVE STATUS\G; *************************** 1. row *************************** [...] Slave_SQL_Running: No [...] Seconds_Behind_Master: NULL [...] Slave_SQL_Running_State: |
Slave_SQL_Running
er “No”, den skal naturligvis helst stå til “Yes”.Seconds_Behind_Master
er “NULL”. Her skal der altid stå et tal.Slave_SQL_Running_State
bør ikke være tom.
Derudover er der i SHOW SLAVE STATUS også information om IO og SQL fejl:
- Last_Error
- Last_Errno
- Last_IO_Error
- Last_IO_Errno
- Last_SQL_Error
- Last_SQL_Errno
Hvis ovenstående felter er tomme, skal du kigge i fejlloggen, der som regel ligger under /var/log/mysql/error.log
.
Eksempler på fejl
Her er det gået grueligt galt. Slaven er kommet så langt bagud, at den ikke kan indhente det tabte:
Last_IO_Errno: | 1236 |
Last_IO_Error: | Got fatal error 1236 from master when reading data from binary log: ‘Could not find GTID state requested by slave in any binlog files. Probably the slave state is too old and required binlog files have been purged.’ |
Her er et par mindre fatale sql fejl. Når det opdages i tide, er det forholdsvist nemt at fikse.
På min master har jeg konfigureret at phpmyadmin databasen IKKE skal med i de binære logfiler. Men PhpMyAdmin har en kedelig uhensigtsmæssighed. Den glemmer at udføre USE phpmyadmin;
før den arbejder med data. Derfor havner disse queries alligevel i loggen og læses af min slave… og da phpmyadmin databasen ikke eksisterer på min slave, fejler den:
Last_SQL_Errno: | 1146 |
Last_SQL_Error: | Error ‘Table ‘phpmyadmin.pma_recent’ doesn’t exist’ on query. Default database: ”. Query: ‘REPLACE INTO phpmyadmin .pma_recent (username , tables ) […] |
Her er der et cronjob der tilsyneladene har en fejl et sted. I hvert fald forsøger den sig med en INSERT der forårsager en “Duplicate entry”:
Last_SQL_Errno: | 1062 |
Last_SQL_Error: | Error ‘Duplicate entry ‘131954’ for key ‘PRIMARY” on query. Default database: ‘shop_live’. Query: ‘INSERT INTO Total (id, blocked, filtered) VALUES(‘131954′,’2′,0)’ |
Her forsøges opdateret en række, der ikke findes på slaven:
Last_SQL_Errno: | 1032 |
Last_SQL_Error: | Could not execute Update_rows_v1 event on table shop_live.StatusDate; Can’t find record in ‘StatusDate’ […] |
Nedenstående fejl har jeg oplevet 2 gange, hvor det begge gange var slavens binære log der var blevet korrupt. Læs mere her: MariaDB replikering: Korrupt binær log på slave
Last_SQL_Errno: | 1594 |
Last_SQL_Error: | Relay log read failure: Could not parse relay log event entry. The possible reasons are: the master’s binary […] |
Det hurtige fiks
Når replikeringen stopper pga SQL fejl, kan du forsøge dig med at springe et par queries over. Den her virker for mig i de fleste tilfælde:
1 |
MariaDB> SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; |
Hvis det ikke virker i første omgang, så prøv at forøge tallet. I ovennævnte eksempel vil replikeringen ignorere de 2 næste queries og derefter fortsætte som normalt. Slaven vil i løbet af kort tid indhente det forsømte. Se efter Seconds_Behind_Master
som gerne skulle gå i 0 efter lidt tid. Skip_Counter
fortæller hvor mange queries den mangler at skippe. Men med så lavt et talt som 2, vil den meget hurtig gå i 0 igen.
Hvis der er fejl du ikke ønsker skal stoppe din replikering, kan du sætte slave-skip-errors
i my.cnf. Her angiver du fejlkode(r) efter behov. Du kan se fejlkoden ud for Last_*_Errno
i output fra SHOW SLAVE STATUS\G
. Flere koder adskilles med komma:
1 2 3 4 5 6 7 8 |
MariaDB> FLUSH TABLES; /etc/mysql/my.cnf: slave-skip-errors = 1062,1146 # service mysql restart MariaDB> START SLAVE; |
Men pas på. Fejl er indikationer på at der er noget galt i et eller andet program/script/job der kommunikerer med databasen, og bør derfor ikke ignoreres medmindre du ved hvad du gør.
Slavens status viser ingen fejlmeddelelser
Hvis der ikke er nogen fejlmeddelelser at se i output fra SHOW SLAVE STATUS
skal du kigge i fejlloggen (som regel /var/log/mysql/error.log
). Her et eksempel:
1 |
Failed to open the relay log './mysqld-relay-bin.000010' (relay_log_pos 104838338) |
Slaven kan af en eller anden årsag ikke læse sin egen logfil og vi skal derfor tvinge den til at oprette en ny. Notér værdierne fra følgende felter i SHOW SLAVE STATUS\G
:
- Relay_Master_Log_File
den binære log på masteren som slaven er igang med at læse fra - Exec_Master_Log_Pos
den position i ovenstående log slaven skal starte fra
Start med at nulstille slaven. Dette tvinger den til at oprette en ny logfil. Normalt vil man udføre en STOP SLAVE kommando først, men i dette tilfælde er slaven allerede stoppen pga. fejlen:
1 |
MariaDB> RESET SLAVE; |
Nu er slaven nulstillet, og vi skal derfor fortælle den hvorfra den skal starte. Erstat værdierne i nedenstående med ovennævnte:
1 2 3 |
MariaDB> CHANGE MASTER TO master_log_file='mariadb-bin.000133', /* Relay_Master_Log_File */ master_log_pos=314603124; /* Exec_Master_Log_Pos */ |
Hvis det er helt galt
Når noget er gået helt galt og din slave er kommet så langt bagud, at det er håbløst at fikse, må du starte forfra. Det er ofte tilfældet når du støder på en Last_IO_Error
.
Find et tidspunkt hvor ingen vigtige cronjobs kører og der er færrest brugere på systemet. Din master vil nemlig blive låst for både læsning og skrivning mens vi laver en backup.
Master
Log på din master server. Lås den og notér dig herefter masterens position:
1 2 |
MariaDB> FLUSH TABLES WITH READ LOCK; MariaDB> SHOW MASTER STATUS\G; |
Eksempel:
1 2 3 4 5 6 |
*************************** 1. row *************************** File: mariadb-bin.000031 Position: 373046832 Binlog_Do_DB: Binlog_Ignore_DB: mysql,replication [...] 1 row in set (0.00 sec) |
Du må IKKE forlade din mysql prompt da dette vil frigøre din lås. Log derfor på i en anden session og lav din backup:
1 |
$ mysqldump -pkode -u bruger --add-drop-database --skip-triggers --routines --databases database1 database2 > masterdump.sql |
Det er vigtigt at du i ovenstående kun udvælger de databaser der normalt skrives til dine binære logfiler.
Gå derefter tilbage i din første session, og lås op igen:
1 |
MariaDB> UNLOCK TABLES; |
Nu er der igen adgang og alt kører som normalt.
Kopiér dit dump til slaven, evt via scp:
1 |
$ scp masterdump.sql bruger@slaveserver.com: |
Nu er vi færdige med din master.
Slave
Log ind på din slave som nu skal stoppes og nulstilles:
1 2 |
MariaDB> STOP SLAVE; MariaDB> RESET SLAVE; |
I en anden session, kan du nu indlæse data fra masteren:
1 |
$ mysql -pkode -u bruger < masterdump.sql |
Ovenstående kan tage laaaaaang tid, afhængig af hvor meget data filen indeholder. Det tog mig omkring ½ time at indlæse en fil på 7GB. Hvis du er i tvivl om der overhovedet sker noget, så prøv at logge på databasen i en anden session og kør SHOW PROCESSLIST et par gange for at se at output ændrer sig.
Nu skal vi fortælle slaven fra hvilket tidspunkt den skal opdatere. Vi ændrer derfor filnavn og position med CHANGE_MASTER_TO og starter derefter slaven igen:
1 2 3 4 |
MariaDB> CHANGE MASTER TO master_log_file='mariadb-bin.000031', master_log_pos=373046832; MariaDB> START SLAVE; |
Tjek status og se at alt kører som det skal:
1 |
MariaDB> SHOW SLAVE STATUS\G; |