relay_log_purge=1仅允许SQL线程在执行完relay log后条件性删除,需满足无句柄占用、无写入冲突等前提,且不保证立即删除,常需FLUSH LOGS触发清理。

relay_log_purge = 0 时,MySQL 完全不自动删 relay log,必须手动干预;设为 1 后,SQL 线程执行完的 relay log 才可能被删,但不保证立刻删除,仍需 FLUSH LOGS 或触发日志轮转。
为什么 SET GLOBAL relay_log_purge = 1 后 relay log 还在
MySQL 的 relay_log_purge 是“条件性清理”开关,不是“立即清理”指令。它只允许 SQL 线程在每次读取并执行完一个 relay log 文件后,尝试删除该文件——但前提是:该文件未被其他线程(如 IO 线程、MHA 检查进程)持有句柄,且当前没有正在写入的 relay log 切片冲突。
常见卡点包括:
- IO 线程正往
relay-bin.000012写入,SQL 线程刚执行完relay-bin.000011,但 MySQL 不会立刻删它,要等下一次FLUSH LOGS或重启触发检查 - 启用了
relay_log_recovery = ON,MySQL 会保留至少一个完整 relay log 做崩溃恢复,阻止最旧文件被删 - 从库延迟严重,
Relay_Master_Log_File和Exec_Master_Log_Pos落后太多,SQL 线程还没真正“执行完”那些文件
手动清理前必须 stop slave 吗
不一定,但强烈建议停。不停 slave 直接删文件,风险在于:
- IO 线程可能正在写入被你
rm的文件,导致写入失败或磁盘 I/O 错误 - SQL 线程正读取中,删掉后报错
Could not parse relay log event entry,复制中断 -
SHOW SLAVE STATUS中的Relay_Log_File和Relay_Log_Pos指向已不存在的文件,START SLAVE失败
安全流程是:
STOP SLAVE;- 确认
Slave_IO_Running: No和Slave_SQL_Running: No - 用
SHOW SLAVE STATUS\G记下Relay_Log_File(比如relay-bin.000015),这是你必须保留的最新文件 - 只删
relay-bin.000015之前的文件,且保留relay-bin.index
purge_relay_logs 工具比 rm 更安全在哪
purge_relay_logs(MHA 自带)不是简单删文件,它做了三件事:
- 先硬链接所有待删 relay log 到
--workdir(同分区!否则硬链接失败),避免大文件rm导致磁盘 I/O 阻塞 - 再执行
SET GLOBAL relay_log_purge = 1+FLUSH LOGS,让 MySQL 主动释放句柄 - 最后批量删硬链接,原文件 inode 被清空,速度极快
关键限制:
-
--workdir必须和 relay log 在同一磁盘分区,否则报错Operation not permitted - 必须指定
--disable_relay_log_purge,否则工具不会改relay_log_purge值 - 密码明文传参有风险,生产环境建议用
~/.my.cnf配置文件替代--user/--password
清理后必须 flush logs 吗
不是必须,但强烈推荐执行 FLUSH LOGS。原因:
- 它会强制 MySQL 重新加载
relay-bin.index,剔除已删文件的记录,避免后续SHOW SLAVE STATUS显示错误的Relay_Log_File - 触发 relay log 轮转,生成新文件(如
relay-bin.000016),让 SQL 线程从干净起点继续 - 若跳过这步,直接
START SLAVE,SQL 线程可能因索引残留尝试读取已删文件,报错Failed to open the relay log
注意:FLUSH LOGS 不影响正在运行的复制,只刷新日志文件句柄,耗时极短。
真正容易被忽略的是 relay-bin.index 文件的完整性——删 relay log 文件后,如果没同步更新这个索引,MySQL 启动或 FLUSH LOGS 时可能 panic。务必用 ls -l 确认 index 文件 mtime 比最新 relay log 更新,否则手动编辑它删掉已不存在的行。


















