能,但需满足relay-log未被清理、位置信息准确且主库binlog未过期;否则无法恢复。

从库崩溃后还能不能靠 relay-log 恢复数据
能,但前提是 relay-log 文件没被清理、relay_log_info_repository = TABLE(或 FILE)里记录的位置还准确,且主库的 binlog 还没过期。一旦 relay-log 被 RESET SLAVE 或异常重启清空,或者 relay_log_purge = ON 自动删了旧文件,这条路就断了。
常见错误现象:Could not parse relay log event entry、Relay log read failure,或启动复制时报 Could not find first log file name in binary log index file —— 往往不是 relay-log 本身损坏,而是位置信息对不上。
- 检查
SHOW SLAVE STATUS\G中的Relay_Log_File和Relay_Log_Pos是否指向一个真实存在的文件和有效偏移 - 确认
relay_log_purge当前值:若为ON,崩溃后可能已自动删除部分 relay-log;建议临时设为OFF再操作 - 用
mysqlbinlog --base64-output=DECODE-ROWS -v手动解析一个 relay-log 文件,看能否输出可读事件(比如INSERT INTO)—— 解析失败说明文件头损坏或不完整
如何用 mysqlbinlog 回放 relay-log 补数据
这不是直接“启动复制”,而是把 relay-log 当成普通 binlog 来回放,绕过 SQL 线程。适用于从库磁盘损坏但 relay-log 完整、且你有主库同版本的 mysqlbinlog 工具的情况。
关键点:必须用与写入 relay-log 相同的 MySQL 版本运行 mysqlbinlog,否则可能解析出错(尤其是 row 格式事件中的列定义差异)。
- 先停掉从库:确保没有其他线程在写或读这些 relay-log
- 定位最新 relay-log:
ls -t /var/lib/mysql/relay-bin.* | head -1(路径以relay_log_basename配置为准) - 回放命令示例:
mysqlbinlog --disable-log-bin --database=mydb /var/lib/mysql/relay-bin.000012 | mysql -u root -p——--disable-log-bin防止再写 binlog,--database限定只回放指定库(避免跨库误操作) - 若报错
Unknown table 'xxx',说明表结构缺失,得先从备份或主库导出CREATE TABLE语句补上
relay-log 位置错位时怎么对齐主库 binlog
崩溃后 Relay_Master_Log_File 和 Exec_Master_Log_Pos 可能停留在某个中间状态,而实际 relay-log 已写到更后面。强行 CHANGE MASTER TO 到这个位置,大概率导致重复或跳过事务。
正确做法是用 mysqlbinlog 查 relay-log 最后一条事件的原始主库坐标(即 SET @@SESSION.GTID_NEXT 或 master_log_file/mast_log_pos 注释),再跟主库 SHOW MASTER STATUS 对齐。
- 解析最后一个 relay-log:
mysqlbinlog -v relay-bin.000015 | tail -30,找末尾类似# at 123456789和#190101 12:34:56 server id 1 end_log_pos 123456789 CRC32 0xabcde的行 - 对比主库当前
File和Position,如果 relay-log 末尾 pos 小于主库当前 pos,说明还有未执行完的事件,可以继续回放;如果大于,说明 relay-log 已超前(几乎不可能,除非手动改过) - 若发现 relay-log 缺失中间段(比如 000012 后直接是 000014),必须去主库拉对应 binlog 补上,不能跳
为什么有时候修复完还是主从不一致
因为 relay-log 只记录“被中继过来的事件”,不保证原子性。比如一个大事务在写入 relay-log 途中崩溃,可能只写了一半;或者 SQL 线程执行到一半中断,而 relay-log 已写全——这时回放 relay-log 会重复执行。
真正保险的做法不是只依赖 relay-log,而是结合 pt-table-checksum 做事后校验,尤其关注 INSERT ... ON DUPLICATE KEY UPDATE、REPLACE INTO、DELETE 这类非幂等操作。
- 修复后务必跑一次
pt-table-checksum --replicate=test.checksums h=slave_host,再用pt-table-sync生成修复语句 - 别忽略
slave_sql_running_state显示Reading event from the relay log时其实可能卡在锁等待,要查SHOW ENGINE INNODB STATUS - 如果从库启用了
slave_parallel_workers > 0,relay-log 里事件顺序可能和主库 binlog 不一致,回放前需确认是否开启slave_preserve_commit_order = ON
最麻烦的情况是:relay-log 没丢,但崩溃发生在事务提交前,InnoDB redo log 里还没落盘,而 relay-log 已写。这时候你回放的是“幻影事务”——看着有,实际没生效。这种只能靠 GTID + 主库 binlog 对比,没法单靠从库文件解决。











