После аварийного рестарта mysql-сервера, исполняющего роль master-а, на slave-е вылезла вот такая проблемка:
[ERROR] Slave I/O: Got fatal error 1236 from master when reading data from binary log: 'Client requested master to start replication from position > file size', Error_code: 1236
Ну и процесс репликации, естественно, остановился.
Как можно догадаться из сообщения об ошибке, slave захотел выполнить команды из такого места бинлога, которого на мастере не оказалось после рестарта последнего (наверное, потому, что часть бинлога не успела записаться на диск мастера за мгновение до того, как он был перезагружен по питанию).
Смотрим позицию, до которой дошел slave:
[slave]$ echo "show slave status \G" | mysql | grep -E "[[:space:]]Master_Log_File|Read_Master_Log_Pos" Master_Log_File: s10-bin.000253 Exec_Master_Log_Pos: 783374391
Смотрим последнюю позицию, которая реально присутствует в этом бинлоге мастера:
[master]$ mysqlbinlog s10-bin.000253 | tail -n 9 /*!*/; # at 783367615 #150704 18:12:45 server id 62 end_log_pos 783367646 CRC32 0x2be04f67 Xid = 22088173 COMMIT/*!*/; DELIMITER ; # End of log file ROLLBACK /* added by mysqlbinlog */; /*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/; /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
И видим, что последняя позиция - 783367646. В то время как slave пытается исполнить позицию 783374391, которая, очевидно, дальше, чем 783367646. Вывод – надо "отмотать" slave немного назад:
[slave] mysql> stop slave; [slave] mysql> change master to master_log_pos=783367646; [slave] mysql> start slave;
В логе видим:
[Note] 'CHANGE MASTER TO executed'. Previous state master_host='10.10.10.10', master_port= 3306, master_log_file='s10-bin.000253', master_log_pos=783374391, master_bind=''. New state master_host='10.10.10.10', master_port= 3306, master_log_file='s10-bin.000253', master_log_pos=783367646, master_bind=''. [Note] Slave I/O thread: connected to master '[email protected]:3306',replication started in log 's10-bin.000253' at position 783367646
Ну и далее show slave status нам говорит, что slave начал догонять master.
Happy end.
P.S. Альтерантивным вариантом посмотреть бинлог является команда SHOW BINLOG EVENTS. Например:
mysql> show binlog events in 's9-bin.000125' from 24084942 limit 10; +---------------+----------+-------------+-----------+-------------+------------------+ | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +---------------+----------+-------------+-----------+-------------+------------------+ | s9-bin.000125 | 24084942 | Write_rows | 8 | 24085025 | table_id: 244461 | | s9-bin.000125 | 24085025 | Update_rows | 8 | 24086045 | table_id: 244461 | | s9-bin.000125 | 24086045 | Write_rows | 8 | 24086128 | table_id: 244461 | | s9-bin.000125 | 24086128 | Update_rows | 8 | 24086518 | table_id: 244461 | | s9-bin.000125 | 24086518 | Write_rows | 8 | 24086600 | table_id: 244461 | | s9-bin.000125 | 24086600 | Update_rows | 8 | 24086876 | table_id: 244461 | | s9-bin.000125 | 24086876 | Write_rows | 8 | 24087008 | table_id: 244461 | | s9-bin.000125 | 24087008 | Update_rows | 8 | 24087138 | table_id: 244461 | | s9-bin.000125 | 24087138 | Write_rows | 8 | 24087221 | table_id: 244461 | | s9-bin.000125 | 24087221 | Update_rows | 8 | 24087611 | table_id: 244461 | +---------------+----------+-------------+-----------+-------------+------------------+ 10 rows in set (0.00 sec)
Но ведь при переключении слейва на позицию в прошлом, разница между позициями будет записана повторно, что вызовет Duplicate entry.
buggy, в данном случае не будет она записана повторно. Потому что на мастере кусок бинлога n потерялся с конца. После ребута мастер начинает новый бинлог n+1. Слейв в старом бинлоге выполнит тольку одну позицию 783367646 и перескочит на следующий бинлог, данных из которого он еще не выполнял.
То есть слейв выполнит только одну 783367646, а не разницу между 783367646 и 783374391.
Admin, спасибо. Если лог действительно был поврежден и записи потерялись, тогда да.
Кстати, если тип репликации row-based (по умолчанию mixed), то чтобы увидеть SQL-операторы, нужно для mysqlbinlog добавить опции --base64-output=DECODE-ROWS --verbose
Заметил прикольную фичу - если на слейве поменять тип репликации (например, добавив в my.cnf binlog_format = row), то мастер автоматически подстраивается, меняя у себя тоже на тот же тип.
Петровский, да реально так и есть.