relay_log_purge=on仅在sql线程完成应用、io线程未写入、无外部进程占用且未被relay_log_recovery锁定时才顺手删除relay log,不满足任一条件即不清理,不可依赖其自动释放磁盘空间。

relay_log_purge 开启了不等于自动清理,它只在特定条件下“顺手删”,不能替代人工判断和操作。
relay_log_purge=ON 为什么经常不删文件
这个参数控制 SQL 线程执行完一个 relay log 后是否尝试删除——但仅当满足全部条件:该文件已完全应用、IO 线程没在写它、无其他进程(如 MHA、备份工具)持有句柄、relay_log_recovery 没锁住最旧文件。
常见卡点:
- 主库长时间没新 binlog,IO 线程不切新 relay log 文件,
relay_log_purge就不触发清理 - 从库延迟高,
Relay_Master_Log_File和Exec_Master_Log_Pos落后太多,MySQL 认为“还没执行完” - 设了
relay_log_purge = ON后直接FLUSH LOGS,看似触发了轮转,但若 SQL 线程卡在 DDL 或大事务里,旧文件仍挂着
PURGE RELAY LOGS TO 'xxx' 的真实行为和风险
命令 PURGE RELAY LOGS TO 'mysql-relay-bin.000027' 不是按时间或内容删,而是按文件名**字典序**删除所有编号小于目标的文件(不含目标本身)。它不做任何复制状态校验。
危险场景:
-
SHOW SLAVE STATUS\G显示Relay_Log_File: mysql-relay-bin.000027,你却删到.000027,结果 SQL 线程一启动就报Could not parse relay log event entry - 文件名被手动改过(比如加了前缀)、或有跳号(
.000010后直接.000012),字典序删会误伤正在写的.000011 -
PURGE RELAY LOGS BEFORE '2026-06-01 00:00:00'语法非法,MySQL 直接报ERROR 1064 (42000)
安全清理必须走 STOP SLAVE + PURGE + START SLAVE 流程
绕过这三步,要么删错,要么删一半被 IO 线程覆盖,导致复制中断。关键动作不是“删”,而是“停住所有读写再删”。
操作顺序:
- 先
SHOW SLAVE STATUS\G,确认Slave_IO_Running: Yes且Seconds_Behind_Master接近 0;记下Relay_Log_File值(比如mysql-relay-bin.000027) - 执行
STOP SLAVE;,等Slave_IO_Running和Slave_SQL_Running都变成No - 运行
PURGE RELAY LOGS TO 'mysql-relay-bin.000027';(删的是.000027之前的所有) - 最后
START SLAVE;,并立刻查SHOW SLAVE STATUS\G确认恢复
用 purge_relay_logs 工具比手写脚本更稳
MHA 自带的 purge_relay_logs 不是简单 rm,它分三阶段规避风险:硬链接待删文件 → SET GLOBAL relay_log_purge = 1; FLUSH LOGS; 让 MySQL 主动释放句柄 → 批量删硬链接(快且不阻塞 I/O)。
但注意两个硬限制:
-
--workdir必须和 relay log 在同一磁盘分区,否则硬链接失败,报Operation not permitted - 必须加
--disable_relay_log_purge参数,否则它会自己关掉relay_log_purge,和你的配置冲突
relay_log_purge 的“自动”二字极具误导性——它不看时间、不批量删、不保底清理,只在 SQL 线程+IO 线程配合默契时才悄悄动一下文件。磁盘告警时,别等它,立刻进库停复制、核对位置、精准 PURGE。











