中继日志占满磁盘时应使用PURGE RELAY LOGS TO 'relay-log.000042'安全清理已执行完的日志,严禁手动rm;需先确认Relay_Log_File、GTID模式及relay_log_purge=ON,并避免与START/STOP SLAVE并发操作。

中继日志(relay log)占满磁盘怎么办
MySQL从库同步卡住、SHOW SLAVE STATUS 显示 Seconds_Behind_Master 持续增长,同时磁盘使用率飙高——大概率是中继日志没清理,堆积在 relay_log_basename 指定路径下。默认情况下,MySQL 不会自动删除已执行完的中继日志,尤其当主库写入频繁、从库延迟大时,relay-log.0000xx 文件能轻松吃掉几十GB空间。
关键不是“能不能删”,而是“删哪些才安全”:必须确保对应日志里的所有事件都已在从库执行完毕,且没有被用于其他用途(比如 GTID 复制中的 relay_log_info_repository = TABLE 依赖部分元数据)。
- 先确认当前正在使用的中继日志:
SHOW SLAVE STATUS\G查看Relay_Log_File字段值(如relay-log.000042),所有序号 小于该文件编号 的relay-log.xxxxxx都可清理 - 检查是否启用了 GTID:
SELECT @@gtid_mode;,若为ON,还需确认Executed_Gtid_Set已覆盖待删日志范围(通常只要Relay_Log_File正确,GTID 模式下也安全) - 不要手动
rm relay-log.*,应使用PURGE RELAY LOGS命令,它会自动更新relay-log.index并通知 MySQL 刷新内部状态
PURGE RELAY LOGS 的正确用法和时机
PURGE RELAY LOGS 是唯一安全的清理方式,它不只是删文件,还会同步修改 relay-log.index 和内存中的日志链表。直接删文件会导致下次启动或 CHANGE MASTER TO 时报错 Failed to open the relay log。
- 立即清理所有已执行完的中继日志:
PURGE RELAY LOGS BEFORE '2024-05-20 00:00:00';(时间戳需早于Relay_Log_File对应的生成时间) - 更稳妥的做法是按文件名清理:
PURGE RELAY LOGS TO 'relay-log.000042';(注意:指定的是「保留到该文件为止」,即TO后面的文件名本身不会被删,但之前所有都会删) - 如果从库启用了
relay_log_purge = OFF(罕见),命令无效,需先SET GLOBAL relay_log_purge = ON;再执行 - 建议在维护窗口执行,避免与
START SLAVE或STOP SLAVE并发操作,否则可能触发ERROR 1981 (HY000): Cannot purge when relay log is active
怎么防止中继日志再次爆满
临时清理只是止痛,真正要解决的是“为什么积压”。常见原因不是磁盘小,而是从库跟不上、或配置没设限。
- 启用自动清理:确保
relay_log_purge = ON(默认就是 ON,但某些定制镜像或旧版本可能关了) - 限制单个中继日志大小:通过
max_relay_log_size控制(如设为512M),避免单个文件过大难清理;注意它不能小于max_binlog_size,否则会被忽略 - 监控延迟:用
Seconds_Behind_Master+Read_Master_Log_Pos与Exec_Master_Log_Pos差值判断积压趋势,而不是等磁盘报警才处理 - 避免在从库上执行大事务或锁表操作,这类操作会阻塞 SQL 线程,导致中继日志持续累积却无法消费
误删中继日志后还能恢复吗
不能。中继日志是二进制日志的本地副本,删了就没了,MySQL 不会从主库重拉已过期的 binlog(除非开启 MASTER_AUTO_POSITION = 1 且主库还保留对应 GTID 范围)。一旦出现 Could not find first log file name in binary log index file 或 Relay log read failure,基本意味着同步断裂。
此时只能重建从库,或从主库导出最新位点并重新 CHANGE MASTER TO。所以 PURGE 前务必核对 Relay_Log_File 和 Relay_Log_Pos,别凭文件名排序瞎猜——ls -t relay-log.* 看的只是创建时间,而 MySQL 实际执行顺序以 relay-log.index 为准。


















