Podczas replikacji MySQL Master-Slave (lub Master-Master) zdarza się sytuacja, w której z różnych przyczyn wersja slave jest niższa niż wersja mastera.
Jeśli używana jest opcja binlog_format=MIXED, może dojść do sytuacji, w której master zapisze w swoim binlogu wpis w postaci:
BINLOG 'XMawShMEAAAARwAAAEp5UwUAAGkAAAAAAAAACHNhblahblahblah'
Którą slave nie będzie w stanie wykonać, ponieważ po prostu „jeszcze jej nie obsługuje”.
Pierwszym sygnałem, że doszło do tego problemu, będzie komunikat „SLAVE DOWN” od systemu monitoringu oraz wpis w logu MySQL slave’a, przypominający poniższy:
090917 14:55:51 [ERROR] Error in Log_event::read_log_event(): 'Found invalid event in binary log', data_len: 71, event_type: 19
090917 14:55:51 [ERROR] Error reading relay log event: slave SQL thread aborted because of I/O error
090917 14:55:51 [ERROR] Slave: 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' o
n 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. Error_code: 0
090917 14:55:51 [ERROR] Error running query, slave SQL thread aborted. Fix the problem, and restart the slave SQL thread with "SLAVE START". We stopped at log 'bin-us1.000022' position 17007149
Próby pominięcia niepożądanych wpisów za pomocą starej, dobrej metody:
slave stop;
set global sql_slave_skip_counter=1;
slave start;
w tym przypadku nie pomagają.
Jako rozwiązanie proponuję:
Zatrzymujemy slave: „SLAVE STOP;”
„Wyciągamy” z tekstu błędu nazwę binloga i pozycję, na której wystąpił błąd.
W tym przypadku jest to bin-us1.000022 i pozycja 17007149
Na masterze wykonujemy zapytanie „FLUSH LOGS;”
Tworzymy dump binloga zaczynając od znalezionej pozycji:
mysqlbinlog --start-position=17007149 bin-us1.000022 > bin-us1-from17007149.sql
Wczytujemy otrzymany dump na slave’ze z kluczem „–force”
mysql --force -uuser -ppassword database < bin-us1-from17007149.sql
Wykonujemy na slave’zie „FLUSH LOGS;”
W katalogu data znajdujemy relay-log o najwyższym numerze i rozmiarze około 100 bajtów (w moim przypadku jest to mysqld-relay-bin.000037)
W tym samym katalogu, w pliku relay-log.info
pierwszy wiersz zastępujemy nazwą właśnie znalezionego relay-loga, do drugiego wpisujemy 0, do trzeciego – kolejny po „zepsutym” binlogu, do czwartego – 0
Powstanie coś w rodzaju:
/var/lib/mysql/mysqld-relay-bin.000037
0
bin-us1.000023
0
Następnie na slave’ze wykonujemy:
CHANGE MASTER TO MASTER_LOG_FILE='bin-us1.000023', MASTER_LOG_POS=0;
SLAVE START;
A następnie, aby upewnić się, że wszystko zadziałało,
SHOW SLAVE STATUS\G
