中继日志损坏的典型错误表现是Last_SQL_Error出现“Relay log read failure”或“Event crc check failed”,此时Slave_SQL_Running为No而Slave_IO_Running通常仍为Yes。

中继日志损坏的典型错误表现是什么
看到 Last_SQL_Error 里出现 Relay log read failure: Could not parse relay log event entry 或 Event crc check failed,基本就是中继日志(relay log)损坏了。这时候 Slave_SQL_Running 会是 No,而 Slave_IO_Running 往往还是 Yes——说明 IO 线程还在正常拉日志,但 SQL 线程卡在损坏位置起不来。
别急着删文件或跳过事件。先确认是不是真损坏:
- 运行
mysqlbinlog --verify-binlog-checksum /path/to/relay-bin.0000xx | head -n 50,如果报Failed to open file或中途退出,基本坐实 - 查 MySQL 错误日志,搜
crc、corrupted、I/O error,配合dmesg -T | grep -i "sd\|nvme"看硬件层有没有扇区报错 - 注意区分:如果
Slave_IO_Running是No,错误在Last_IO_Error,那大概率是网络、权限或主库 binlog 问题,跟 relay log 无关
为什么不能直接删 relay-log 文件再 START SLAVE
relay-log 不是缓存,是未执行事件的“待办清单”。SQL 线程的当前位置(Relay_Log_File 和 Relay_Log_Pos)已经指向损坏文件里的非法偏移。你手动删掉所有 relay-bin.* 和 relay-log.index 后直接 START SLAVE,MySQL 不会自动重建有效中继日志,反而会让 SQL 线程从一个空起点开始——要么跳过已拉取但未执行的事件,要么因位置不匹配直接报错中断。
更危险的是:IO 线程可能还在往旧文件名写入新事件,删完后它继续追写,但文件名已被清空,导致日志丢失或覆盖。
安全重置 relay-log 的三步操作
核心是丢掉损坏的 relay log,但保留 IO 线程已拉取到的最新位置(即 Master_Log_File 和 Master_Log_Pos),让 SQL 线程从那里重新开始执行。
STOP SLAVE;- 记下
SHOW SLAVE STATUS\G中的Master_Log_File(如mysql-bin.000123)和Master_Log_Pos(如456789)——这是唯一可信的“已同步到主库哪”的坐标 -
RESET SLAVE;—— 这会清空所有 relay log 文件、重置relay-log.index,同时把Relay_Master_Log_File和Exec_Master_Log_Pos清空,但Master_Log_File/Master_Log_Pos不变 CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000123', MASTER_LOG_POS=456789;START SLAVE;
做完这五步,SQL 线程会从主库 binlog 的指定位置重放,跳过损坏的 relay log,也避免重复或丢失。
要不要开 relay_log_recovery=1
这个参数确实能在从库意外宕机重启时自动触发类似上面的重置流程,但它只在 mysqld 启动阶段生效,且要求配置文件里显式设置并重启服务——不能动态开启。生产环境建议提前打开:
- 在
my.cnf的[mysqld]段加relay_log_recovery = ON - 配套加上
skip-slave-start = 1,防止服务启动时自动拉起复制,给人工检查留出窗口 - 注意:该参数对已运行中的复制无效,只管下次启动
真正麻烦的不是操作本身,而是损坏发生后你无法判断哪些事件已执行、哪些卡在损坏文件里。所以日常必须配合 pt-table-checksum 定期校验主从一致性,而不是等报错才动手。


















