Das MySQL-Relay-Protokoll ist beschädigt. Wie behebe ich das? Versucht aber gescheitert

25

Ein MySQL-Relay der Version 5.1.61 wurde beschädigt, als die Maschine plötzlich herunterfuhr. Ich habe versucht, es zu beheben, aber es hat nicht funktioniert.
- Wie behebe ich das? Habe ich etwas falsch gemacht?

Nach meinem Kenntnisstand können beschädigte MySQL-Relay-Protokolle leicht behoben werden:

change master to master_log_file='<Relay_Master_Log_File>',
                 master_log_pos=<Exec_Master_Log_Pos>;

wo Relay_Master_Log_Fileund Exec_Master_Log_Possind aufgelistet nach:
mysql> show slave status;

Als ich das tat change master status ..., bekam ich einen Fehler wegen einer Verletzung des Primärschlüssels. Wie ist das möglich? Ist die obige Prozedur nicht korrekt oder fehlt zB etwas +1?

(Im Moment habe ich einfach einen --master-data mysqldump vom Master zum Slave reimportiert, und das hat das Problem gelöst. In Zukunft könnte dies jedoch nicht angebracht sein.)


Hier folgen Details zu meinem speziellen Problem:

mysql> show slave status \G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: the-master-host
                  Master_User: replication
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000021
          Read_Master_Log_Pos: 33639968
               Relay_Log_File: mysql-relay-bin.000271
                Relay_Log_Pos: 2031587
        Relay_Master_Log_File: mysql-bin.000020
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB: the_database
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 1594
                   Last_Error: Relay log read failure: Could not parse relay log event entry. The possible reasons are: the master's binary log is corrupted (you can check this by running 'mysqlbinlog' on the binary log), the slave's relay log is corrupted (you can check this by running 'mysqlbinlog' on the relay log), a network problem, or a bug in the master's or slave's MySQL code. If you want to check the master's binary log or slave's relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' on this slave.
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 66395191
              Relay_Log_Space: 36559177
              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: 1594
               Last_SQL_Error: Relay log read failure: Could not parse relay log event entry. The possible reasons are: the master's binary log is corrupted (you can check this by running 'mysqlbinlog' on the binary log), the slave's relay log is corrupted (you can check this by running 'mysqlbinlog' on the relay log), a network problem, or a bug in the master's or slave's MySQL code. If you want to check the master's binary log or slave's relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' on this slave.

Und das habe ich getan:

mysql> stop slave;
mysql> reset slave;
mysql> change master to master_host='the-master-host', master_user='replication', master_password='the-password', master_log_file='mysql-bin.000020', master_log_pos=66395191;
mysql> start slave;

Und das ist passiert, ein PK-Fehler:

131122 15:17:29 [Note] Slave I/O thread: connected to master 'replication@the-master-host:3306',replication started in log 'mysql-bin.000020' at position 66395191
131122 15:17:29 [ERROR] Slave SQL: Error 'Duplicate entry '71373' for key 'PRIMARY'' on query. Default database: 'the_database'. Query: 'insert into ...  values ...', Error_code: 1062
131122 15:17:29 [Warning] Slave: Data truncated for column 'date' at row 1 Error_code: 1265
131122 15:17:29 [Warning] Slave: Duplicate entry '71373' for key 'PRIMARY' Error_code: 1062

Ich denke , dass ich das empfohlene Verfahren gefolgt (siehe Links unten nur), noch gab es einen PK Fehler :-(? Http://bugs.mysql.com/bug.php?id=26489 , wenn nach „Workarounds“. Http: //mhbarr.wordpress.com/2013/07/26/mysql-slave-corrupted-relay-log/ /programming//a/14438408

KajMagnus
quelle
1
Ja, es sieht so aus, als hätte es funktionieren sollen, und tatsächlich sieht es so aus, als hätte es tatsächlich funktionieren sollen, da möglicherweise das ursprüngliche Relay-Protokoll vor dem beschädigten Abschnitt das Einfügen an dieser Master-Protokollposition bereits durchgeführt hatte, aber nicht vorrücken konnte Die Position des Masters zum nächsten Zeiger wird angezeigt, da dieser Zeiger im Relay-Protokoll gespeichert ist (was fehlerhaft war.). Möglicherweise haben Sie also dieses Ereignis übersprungen und sind zum nächsten Ereignis übergegangen, um dann zu überprüfen, ob Master und Slave tatsächlich identische Daten hatten ... Ich hatte noch keine Gelegenheit, die Frage ausreichend detailliert zu prüfen.
Michael - sqlbot
1
Danke @ Michael-sqlbot, dann denke ich, wenn dieses Problem erneut auftritt, SET GLOBAL sql_slave_skip_counter = 1; START SLAVE;überspringe ich ein Ereignis für den Sklaven und hoffe, das hilft - macht das Sinn? Wenn es nicht hilft (wenn es immer noch einen PK-Fehler gibt), importiere ich erneut einen Dump mit --master-data.
KajMagnus

Antworten:

34

Fehler: Last_SQL_Errno: 1594 Last_SQL_Error: Fehler beim Lesen des Relaisprotokolls: Der Ereigniseintrag des Relaisprotokolls konnte nicht analysiert werden.

Dieser Fehler bedeutet, dass entweder die Master-Protokolldatei oder die Relay-Protokolldatei beschädigt ist.

  • Bevor Sie etwas tun, sichern Sie alle Ihre Datenbanken, Protokolle und Image-Server mehrmals und fahren Sie nur auf eigenes Risiko fort.

Führen Sie zuerst "show slave status \ G" auf dem Slave aus und beachten Sie:

Master_Log_File: mysql-bin.000026
Read_Master_Log_Pos: 2377104
Relay_Log_File: mysqld-relay-bin.000056
Relay_Log_Pos: 1097303
Relay_Master_Log_File: mysql-bin.000026
Exec_Master_Log_Pos: 1097157

Zuerst möchten wir sicherstellen, dass die Master-Protokolldatei intakt ist. Wechseln Sie also zum Master-Server und suchen Sie die Relay_Master_Log_File (check / var / log / mysql) und führen Sie den folgenden Befehl aus:

mysqlbinlog mysql-bin.000026

Das Protokoll wird angezeigt, es werden jedoch hoffentlich keine Fehlermeldungen angezeigt. Wenn Sie Fehlermeldungen sehen, sind die Master-Protokolle beschädigt und Sie müssen wahrscheinlich ein neues Image erstellen.

Führen Sie als Nächstes denselben Befehl im Slave-Relay-Protokoll aus (häufig in / var / lib / mysql).

mysqlbinlog mysqld-relay-bin.000056

Sie werden wahrscheinlich einige Fehler sehen, die die Beschädigung anzeigen, die die Replikation gestoppt hat:

ERROR: Error in Log_event::read_log_event(): 'read error', data_len: 336, event_type: 2
ERROR: Could not read entry at offset 1097414: Error in log format or read error.
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
root@db:/var/lib/mysql#

Wenn Sie Fehler sehen, ist das Protokoll auf dem Master in Ordnung und nur das Relaisprotokoll des Slaves ist beschädigt. Dies ist eine gute Nachricht, wir können den Slave zurücksetzen und ihm die Details des Masters mitteilen und wo er weitermachen soll. Wenn Sie keine Fehler sehen, hören Sie jetzt auf zu lesen, haben Sie ein anderes Problem.

Wenn das Slave-Relay-Protokoll Fehler aufweist, führen Sie die folgenden Befehle aus, um den Slave zurückzusetzen und beschädigte Protokolle wieder mit dem Master zu verbinden. Rufen Sie die ordnungsgemäßen Protokolle ab und beginnen Sie erneut mit dem Slaven. Beachten Sie, dass MASTER_LOG_POS das Exec_Master_Log_Posist und MASTER_LOG_FILE das ist Relay_Master_Log_File( NICHT das erste, das Relay-Protokolle entspricht, die abgerufen wurden und weggeworfen werden müssen), beide aus dem ersten Befehl.

mysql> stop slave;
Query OK, 0 rows affected (0.14 sec)

mysql> reset slave all;
Query OK, 0 rows affected (0.43 sec)

mysql>  CHANGE MASTER TO MASTER_HOST='master.host.com', MASTER_USER='masteruser', MASTER_PASSWORD='masterpass', MASTER_LOG_FILE='mysql-bin.000026', MASTER_LOG_POS=1097157;
Query OK, 0 rows affected (0.93 sec)

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
A.Badger
quelle
2
Hallo, danke für deine Antwort. Wenn Sie die Frage sorgfältig lesen, werden Sie feststellen, dass die Meldung "Relay-Protokoll beschädigt" lautet. Dies liegt daran, dass wir bereits mysqlbinlogdie von Ihnen vorgeschlagene Methode angewendet haben und festgestellt haben, dass das Relay-Protokoll (nicht das Master-Protokoll) beschädigt ist. Anhand der von Ihnen vorgeschlagenen Fehlerbehebung - Wenn Sie die Frage sorgfältig lesen, werden Sie feststellen, dass die von Ihnen vorgeschlagene Fehlerbehebung genau das ist, was wir bereits versucht haben. Aber das hat nicht funktioniert, und darum geht es in der Frage. - Aber Ihre Antwort könnte für andere Personen mit einem ähnlichen Problem nützlich sein.
KajMagnus
2
Es sollte wohl angemerkt werden, dass MASTER_LOG_FILEin aus genommen CHANGE MASTERwerden soll Relay_Master_Log_Fileund nicht aus Master_Log_File. Normalerweise sind sie gleich, aber es kann sein, dass dies nicht immer der Fall ist (siehe percona.com/blog/2008/07/07/… ).
Brablc
@brablc ist richtig. Relay_Master_Log_Filemuss verwendet werden, nicht Master_Log_File. Siehe auch: percona.com/blog/2008/07/07/…
Mircea Vutcovici
In den meisten Fällen ist reset slave alldies nicht erforderlich, da die Master-Einstellungen nicht geändert werden müssen (z. B. master_host, master_user, master_password), sondern nur MASTER_LOG_FILE und MASTER_LOG_POS. Dann reset_slavesollte a ausreichen
ympostor 14.07.17
Diese Frage und Antwort hat meinen Hintern schon mehrmals gerettet. Vielen Dank.
Artem Russakovskii
8

[Behebung der MySQL-Replikation, nachdem das Relay-Protokoll der Slaves beschädigt wurde]

Die MySQL-Replikation auf dem Slave (Version 5.XX) wurde gestoppt. Slave_IO_Running wurde als Ja markiert, Slave_SQL_Running als Nein. Ein einfacher Stopp / Start-Slave half nicht, sodass eine weitere Problemanalyse erforderlich war. Das Relay-Protokoll des aktuellen Slaves schien beschädigt zu sein, da beim Testen mit "mysqlbinlog" ein Fehler ausgegeben wurde. Daher bestand die Lösung darin, aktuelle Relais-Binlogs zu verwerfen und den Slave auf die letzte Master-Binlog-Position zu verweisen.

Um den Fehler zu beheben, sollten die aktuellen Binlog-Dateien auf dem Slave verworfen und eine neue Position festgelegt werden. Bevor Sie eine neue Binlog-Position festlegen, müssen Sie sich die Relay_Master_Log_File- und Exec_Master_Log_Pos- Werte vom beschädigten Slave-Server mit dem Befehl SHOW SLAVE STATUS \ G merken :

Relay_Master_Log_File: mysql-bin.002045
Exec_Master_Log_Pos: 103641119

OK, mit diesen Werten kann die neue Binlog-Position festgelegt werden:

# stop slave
mysql> stop slave;

# make slave forget its replication position in the master's binary log
mysql> reset slave;

# change slave to start reading from stopped position
mysql> change master to master_log_file='mysql-bin.002045', master_log_pos=103641119;

# start slave
mysql> start slave;

Nur um zu merken, dass alle Relay-Protokolldateien reset slavegelöscht master.infowerden relay-log.infound es nicht erforderlich ist, Reste im /var/lib/mysqlVerzeichnis zu entfernen .

Mohamed Ayas
quelle
1
Gute Antwort - normalerweise müssen wir den Master-Host, das Passwort usw. nicht ändern. Thx!
andy250
3

Ich weiß, dass es über ein Jahr her ist, aber hier ist, was mit diesem speziellen Problem passiert sein könnte.

mysql> stop slave;
mysql> reset slave;
mysql> change master to master_host='the-master-host', master_user='replication', master_password='the-password', master_log_file='mysql-bin.000020', master_log_pos=66395191;
mysql> start slave;

Das sieht so aus, als hätte das Problem behoben werden müssen, da das beschädigte Relay-Protokoll entfernt wurde.

Dann haben Sie einen PK-Fehler 1062 erhalten. Warum?

In MySQL 5.5 gibt es einen noch offenen Fehler ( http://bugs.mysql.com/bug.php?id=60847 )

Obwohl sich der Fehler auf die Verwendung von mysql --single-transaction --flush-logs bezieht, gibt es eine verwandte Besonderheit.

Ich habe diese Eigenart auf einigen EC2-Servern gesehen, die erst letzte Woche in MySQL 5.5.15 als Slaves für einen Client ausgeführt wurden

Auf dem Master gab es ein seltsames mehrzeiliges erweitertes INSERT, bei dem jedes eingefügte Tupel ein SELECT war. Was geschah, war, dass die LAST_INSERT_ID im Relaisprotokoll, die das nächste zuzuweisende automatische Inkrement darstellt, bereits auf dem Slave verwendet wurde, da zuvor mehrere Zeilen eingefügt wurden.

Das serialisierte INSERT im Relaisprotokoll sah wie folgt aus

INSERT INTO tablname (column,column) VALUES (value,value,...)

Die Spaltenliste enthielt keinen numerischen Primärschlüssel. Wenn der 1062-Fehler wieder auftritt, verwende ich dieselbe Abfrage, bei der er fehlgeschlagen ist. Führen Sie die Abfrage manuell aus. Der 1062-Fehler ist nicht aufgetreten. Dann habe ich die üblichen skip slave Befehle ausgeführt:

STOP SLAVE;
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
START SLAVE;
SET @sleepnumber = SLEEP(3);
SHOW SLAVE STATUS\G

Dann holte die Replikation auf.

Mein Rat wäre, Ihre INSERTs auf dem Master richtig zu serialisieren, da diese fehlerhafte Situation eigentlich ganz vermieden werden kann.

RolandoMySQLDBA
quelle
1

Du hast es ganz richtig gemacht (wie andere schon sagten).

Das einzige Problem betrifft die Datei master.info (enthält Informationen zur Position in mysql-bin.log des Masters), da diese Datei nach jeder verarbeiteten Abfrage nicht mit dem Datenträger synchronisiert wird.

Ihre Informationen zu Positionen im Master-Protokoll sind daher veraltet und Sie verarbeiten bereits verarbeitete Anfragen, die übersprungen werden müssen SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;.

Leider, wenn Sie einige Abfragen wie verwenden UPDATE table SET counter=counter+1 WHERE id = 12345und binlog_format=STATEMENTIhre Datenbanken möglicherweise nicht synchron sind, denke ich.

Sie können MySQL Server anweisen, master.info nach jedem Ereignis zu synchronisieren, indem Sie die Variable sync_master_info einrichten. Dies wird jedoch wahrscheinlich enorme Auswirkungen auf die Leistung haben.

Dragonn
quelle