某客户 MySQL 主从集群出现复制故障,从库 SQL 线程停止并报错 1594,IO 线程仍正常拉取日志。通过SHOW SLAVE STATUS
观察到关键信息:
Slave_SQL_Running: No
Last_Errno: 1594
Last_Error: Relay log read failure: Could not parse relay log event entry.
错误日志进一步显示Event crc check failed
,表明中继日志(Relay Log)的 CRC 校验失败,数据存在损坏。
MySQL 在解析日志事件时会进行 CRC32 校验,若校验失败,说明日志数据在存储或传输过程中发生损坏。常见诱因包括:
- 物理存储故障:磁盘坏道、RAID 卡异常导致中继日志文件损坏
- 写入中断:MySQL 服务异常重启、操作系统崩溃打断日志写入
- 网络传输错误:主从复制网络波动导致日志传输不完整
- 事务分片异常:超大事务(超过
max_allowed_packet
)分片写入时出错
从库错误日志显示:
2024-12-29T00:22:19.824988+08:00 [ERROR] Error in Log_event::read_log_event(): 'Event crc check failed!'
通过mysqlbinlog --verify-binlog-checksum
解析中继日志,发现特定位置的事件校验失败,且最后一个事务未完整写入,印证了日志损坏的判断。
- MySQL 版本:5.7.26,启用 GTID
- 从库状态:IO 线程运行正常,SQL 线程停止
- 关键参数:
max_allowed_packet=16M
,事务大小计算为 20M(排除参数限制)
- 系统层检查:查看故障时段系统日志,无磁盘错误或 OOM(Out of Memory)记录
- 主库健康度:主库 binlog 文件完整,服务状态正常,网络监控无异常
- 事务完整性:通过 GTID 定位故障事务,确认其大小虽超过参数但非核心原因
- 中继日志验证:使用
mysqlbinlog
解析 relay log,发现 CRC 校验失败点
为验证成因,在测试环境执行以下步骤:
- 准备主从环境:搭建 5.7.26 主从集群,确认复制正常
- 暂停 SQL 线程:
STOP SLAVE SQL_THREAD;
- 手动损坏中继日志:使用
hexedit
修改mysql-relay.000007
文件内容
- 重启 SQL 线程:
START SLAVE SQL_THREAD;
复现结果与生产环境一致:
Last_Errno: 1594
Last_Error: Relay log read failure: Could not parse relay log event entry.
错误日志同步输出Event crc check failed
,确认中继日志损坏是 1594 报错的直接原因。
- 保留现场数据:先备份故障时的 relay log 和错误日志
- 重置主从复制:执行
RESET SLAVE;
并重新搭建复制链路
- 验证日志完整性:使用
mysqlbinlog --verify-binlog-checksum
检查所有日志
-
硬件层面:
- 部署 RAID1/10 磁盘阵列,定期进行磁盘健康检查
- 为 MySQL 服务配置 UPS 电源,避免突然断电
-
参数优化:
-
监控体系:
- 增加 relay log CRC 校验监控,定期执行
mysqlbinlog --verify
- 监控从库 SQL 线程状态,设置异常告警机制
在启用 GTID 的集群中,可通过以下方式提升恢复效率:
- 定位故障 GTID:从
SHOW SLAVE STATUS
获取最后成功应用的 GTID
- 跳过损坏事务:
SET GLOBAL gtid_purged='已完成的GTID集合';
START SLAVE;
- 增量重建:仅重建损坏事务后的复制,避免全量数据同步
MySQL 主从复制 1594 报错本质是中继日志的完整性危机,其排查需结合错误日志分析、系统状态检查和环境复现。在生产环境中,完善的备份策略、硬件可靠性保障及实时监控体系,是预防此类故障的核心手段。通过本次分析可见,数据库故障处理中保留现场数据与系统化排查逻辑,是快速定位问题的关键。