Uszkodzony dziennik przekazywania MySQL, jak to naprawić? Próbowałem, ale nie powiodło się

25

Przekaźnik MySQL v5.1.61 został uszkodzony, gdy maszyna nagle się wyłączyła. Próbowałem to naprawić, ale to nie działało.
- Jak to naprawić? Czy zrobiłem coś nie tak?

O ile czytałem, uszkodzone dzienniki przekazywania MySQL można łatwo naprawić:

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

gdzie Relay_Master_Log_Filei Exec_Master_Log_Possą wymienione przez:
mysql> show slave status;

Jednak kiedy to zrobiłem change master status ..., wystąpił błąd naruszenia klucza podstawowego. Jak to możliwe? Czy powyższa procedura jest nieprawidłowa, czy brakuje np. Niektórych +1?

(Na razie po prostu ponownie zaimportowałem --master-data mysqldump z urządzenia nadrzędnego do urządzenia podrzędnego, co rozwiązało problem. Jednak w przyszłości może to być nieodpowiednie).


Oto szczegóły dotyczące mojego konkretnego problemu:

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.

I to właśnie zrobiłem:

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;

I tak się stało, błąd PK:

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

Wydaje mi się, że postępowałem zgodnie z zalecaną procedurą (patrz linki poniżej), nadal wystąpił błąd PK :-(? Http://bugs.mysql.com/bug.php?id=26489 , wyszukaj „Obejścia”. Http: //mhbarr.wordpress.com/2013/07/26/mysql-slave-corrupt-relay-log/ /programming//a/14438408

KajMagnus
źródło
1
Tak, wygląda na to, że powinien był zadziałać i faktycznie wygląda na to, że prawdopodobnie faktycznie działał, ponieważ być może oryginalny dziennik przekazywania, przed uszkodzoną sekcją, już wstawił wstawkę w tej pozycji dziennika głównego, ale nie mógł przesuwać wyświetlał pozycję master do następnego wskaźnika, ponieważ ten wskaźnik jest przechowywany w dzienniku przekaźników (co było uszkodzone). Być może omijałeś to zdarzenie i przechodziłeś do następnego zdarzenia, a następnie weryfikowałeś, czy master i slave faktycznie mieli identyczne dane ... Nie miałem jeszcze okazji przejrzeć pytania wystarczająco szczegółowo.
Michael - sqlbot
1
Dzięki @ Michael-sqlbot, więc myślę, że jeśli ten problem się powtórzy, zrobię SET GLOBAL sql_slave_skip_counter = 1; START SLAVE;i pominę jedno zdarzenie na niewolniku i mam nadzieję, że to pomoże - czy to ma sens? Jeśli to nie pomoże (jeśli nadal występuje błąd PK), --master-dataponownie zaimportuję zrzut .
KajMagnus

Odpowiedzi:

35

Błąd: Last_SQL_Errno: 1594 Last_SQL_Error: Błąd odczytu dziennika przekazywania: Nie można przeanalizować wpisu dziennika zdarzeń przekazywania.

Ten błąd oznacza, że ​​główny plik dziennika jest uszkodzony lub plik dziennika przekazywania jest uszkodzony.

  • Zanim cokolwiek zrobisz, wykonaj kopię zapasową wszystkich baz danych, dzienników, serwerów obrazów, powtórz kilka razy i kontynuuj tylko na własne ryzyko.

Najpierw uruchom „show slave status \ G” na slave i zwróć uwagę:

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

Najpierw chcemy się upewnić, że główny plik dziennika jest nienaruszony, więc przeskocz na serwer główny i znajdź plik Relay_Master_Log_File (sprawdź / var / log / mysql) i uruchom następującą komendę:

mysqlbinlog mysql-bin.000026

Dziennik zostanie wyświetlony, ale mam nadzieję, że nie zobaczysz żadnych komunikatów o błędach. Jeśli zobaczysz komunikaty o błędach, dzienniki główne są uszkodzone i prawdopodobnie będziesz musiał ponownie wykonać zdjęcie.

Następnie uruchom tę samą komendę w dzienniku przekaźników podrzędnych (często w / var / lib / mysql)

mysqlbinlog mysqld-relay-bin.000056

Prawdopodobnie zobaczysz kilka błędów pokazujących uszkodzenie, które zatrzymało replikację, na przykład:

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#

Jeśli zobaczysz jakieś błędy, oznacza to, że dziennik jest poprawny w urządzeniu głównym i tylko dziennik przekaźnika urządzenia podrzędnego jest uszkodzony. To dobra wiadomość, możemy zresetować niewolnika i podać mu szczegóły panów oraz dokąd kontynuować. Jeśli nie widzisz żadnych błędów, przestań czytać teraz, masz inny problem.

Jeśli w dzienniku przekaźnika podrzędnego występują błędy, uruchom następujące polecenia, aby zresetować dziennik podrzędny, a uszkodzone dzienniki ponownie połączą się z urządzeniem głównym, uzyskaj dzienniki OK i ponownie rozpocznij podporządkowanie. Zauważ, że MASTER_LOG_POS jest Exec_Master_Log_Pos, a MASTER_LOG_FILE to Relay_Master_Log_File( NIE pierwszy, który pasuje do logów przekaźników, które zostały pobrane i należy je wyrzucić) od pierwszego polecenia.

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
źródło
2
Cześć, dzięki za odpowiedź. Jeśli uważnie przeczytasz pytanie, zauważysz, że napis „Uszkodzony dziennik przekaźników” - to dlatego, że użyliśmy już mysqlbinlogsposobu, który sugerujesz, i odkryłeś, że dziennik przekaźników (nie główny dziennik) został uszkodzony. Uwzględniając proponowaną poprawkę - jeśli dokładnie przeczytasz pytanie, zauważysz, że sugerowana poprawka jest dokładnie tym, co już próbowaliśmy. Ale to nie zadziałało i o to właśnie chodzi. - Ale twoja odpowiedź może być przydatna dla innych osób z podobnym problemem.
KajMagnus
2
Powinna ona prawdopodobnie zauważyć, że MASTER_LOG_FILEw CHANGE MASTERpowinny być podejmowane z Relay_Master_Log_File, a nie Master_Log_File. Zwykle będą takie same, ale nie zawsze tak jest (patrz percona.com/blog/2008/07/07/… ).
brablc
@brablc ma rację. Relay_Master_Log_Filenależy użyć, nie Master_Log_File. Zobacz także: percona.com/blog/2008/07/07/…
Mircea Vutcovici,
w większości przypadków nie ma takiej potrzeby, reset slave allponieważ ustawienia główne nie muszą być zmieniane (np. master_host, master_user, master_password), tylko MASTER_LOG_FILE i MASTER_LOG_POS, to reset_slavepowinno wystarczyć
ympostor
To pytanie i odpowiedź już kilkakrotnie uratowały mi tyłek. Dziękuję Ci.
Artem Russakovskii
8

[Naprawianie replikacji MySQL po uszkodzeniu dziennika przekaźników slave]

Replikacja MySQL na slave (wersja 5.XX) została zatrzymana. Slave_IO_Running został oznaczony jako Tak, ale Slave_SQL_Running jako Nie. Proste zatrzymanie / uruchomienie slave nie pomogło, więc potrzebna była dalsza analiza problemu. Wydawało się, że dziennik przekaźników bieżącego urządzenia podrzędnego został uszkodzony, ponieważ podczas testowania za pomocą „mysqlbinlog” wystąpił błąd. Dlatego rozwiązaniem było odrzucenie bieżących binlogów przekaźnika i skierowanie slave'a do ostatniej głównej pozycji binlog.

Aby naprawić błąd, bieżące pliki binlog na slave należy odrzucić i ustawić nową pozycję. Przed ustawieniem nowej pozycji binlog należy pamiętać o wartości Relay_Master_Log_File i Exec_Master_Log_Pos z uszkodzonego serwera slave za pomocą polecenia SHOW SLAVE STATUS \ G :

Relay_Master_Log_File: mysql-bin.002045
Exec_Master_Log_Pos: 103641119

OK, przy pomocy tych wartości można ustawić nową pozycję binlog:

# 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;

Wystarczy zauważyć, że reset slavebędzie usunąć master.info, relay-log.infoi wszystkich plików dziennika przekaźnik, więc to nie jest konieczne, aby oczyścić resztki w /var/lib/mysqlkatalogu.

Mohamed Ayas
źródło
1
Dobra odpowiedź - zazwyczaj nie musimy zmieniać hosta głównego, hasła itp. Dzięki!
andy250
3

Wiem, że minął ponad rok, ale oto, co mogło się stać z tym konkretnym problemem.

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;

Wygląda na to, że powinien to naprawić, ponieważ usunął uszkodzony dziennik przekazywania.

Wystąpił błąd PK 1062. Dlaczego?

Istnieje zaległy błąd ( http://bugs.mysql.com/bug.php?id=60847 ), który nadal jest aktywny w MySQL 5.5

Chociaż błąd dotyczy używania mysql --single-transaction --flush-logs, istnieje podobne dziwactwo.

W zeszłym tygodniu widziałem to dziwactwo na niektórych serwerach EC2 działających jako Slaves dla klienta w MySQL 5.5.15

Na Master był dziwny, wielorzędowy rozszerzony WSTAW, w którym wstawiana krotka była WYBRANA. Stało się tak, że LAST_INSERT_ID w dzienniku przekaźników, który tworzy następny automatyczny przyrost, który został przypisany, był już używany w Slave z powodu wcześniejszych wstawek z wieloma wierszami.

Serial INSERT w dzienniku przekaźnika wyglądał

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

Lista kolumn nie zawierała numerycznego klucza podstawowego. Gdy wrócił błąd 1062, użyłbym tego samego zapytania, na którym nie powiodło się, uruchom zapytanie ręcznie. Nie trafił w błąd 1062. Następnie uruchomiłem zwykłe polecenia pominięcia niewolnika:

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

Następnie replika nadrobiła zaległości.

Moja rada byłaby odpowiednia serializacja twoich WSTAWEK na Master, ponieważ taka sytuacja podobna do błędów jest właściwie całkiem do uniknięcia.

RolandoMySQLDBA
źródło
1

Zrobiłeś to całkiem dobrze (jak inni już powiedzieli).

Jedyny problem dotyczy pliku master.info (zawiera informacje o pozycji w mysql-bin.log), ponieważ plik ten nie jest synchronizowany z dyskiem po przetworzeniu każdego zapytania.

Twoje informacje o pozycjach w dzienniku głównym są nieaktualne i przetwarzasz już przetworzone zapytania, które należy pominąć SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1;.

Niestety, jeśli użyjesz takich zapytań jak UPDATE table SET counter=counter+1 WHERE id = 12345i korzystanie binlog_format=STATEMENTz baz danych może się nie zsynchronizować, myślę.

Możesz powiedzieć serwerowi MySQL, aby synchronizował master.info po każdym zdarzeniu, ustawiając zmienną sync_master_info, ale prawdopodobnie będzie to miało ogromne konsekwencje dla wydajności.

Dragonn
źródło