relay_log_purge=ON 不会立即自动删除,仅标记已应用完的 relay log 为“可删”,真正删除需等待 IO 线程写入新文件;SQL 线程卡住或 STOP SLAVE 后未启动均会导致旧日志堆积。

relay_log_purge=ON 是不是开了就自动删?
不是。即使 relay_log_purge=ON(默认值),MySQL 也只在 SQL 线程执行完某段 relay log 后才标记为“可删”,真正删除动作发生在下次 IO 线程写入新 relay log 文件时——也就是说,** 不写新日志,旧的就一直留着 **。
常见错误现象:SHOW SLAVE STATUSG 显示 Relay_Log_File 指向 relay-bin.000012,但磁盘里还堆着 relay-bin.000001 到 .000010;或者主库没更新、从库空闲数小时,relay log 却一动不动。
- 必须有新的 binlog 事件被拉取(IO 线程写入新 relay log),才会触发清理已应用完的旧文件
- 如果 SQL 线程卡住(比如遇到 DDL 锁、大事务回放慢),即使 relay log 已读完,也不会删——因为 MySQL 认为“还没应用完”
-
relay_log_purge是动态变量,SET GLOBAL relay_log_purge=OFF后,后续所有 relay log 都不会被自动清理,哪怕 SQL 线程追上了
手动清理 relay log 的安全操作步骤
不能直接 rm -f relay-bin.*,否则可能破坏复制状态或导致启动失败。正确做法是用 MySQL 内置命令,由 server 自行校验后清理。
- 先确认 SQL 线程已追平:
Seconds_Behind_Master: 0且Relay_Master_Log_File == Master_Log_File,Exec_Master_Log_Pos == Read_Master_Log_Pos - 执行
PURGE RELAY LOGS TO 'relay-bin.000015';—— 注意指定的是「保留到哪个文件为止」,即删除 早于relay-bin.000015的所有 relay log(不含该文件本身) - 若想清空全部(慎用!仅限重搭从库前):
PURGE RELAY LOGS BEFORE '2024-01-01 00:00:00';,时间需早于Relay_Log_File对应的Relay_Log_Pos时间戳 - 加
WITH GTID不生效——PURGE RELAY LOGS不支持 GTID 条件过滤,只认文件名或时间
为什么 FLUSH LOGS 有时会意外删掉 relay log?
FLUSH LOGS 本身不删 relay log,但它会强制 IO 线程关闭当前 relay log 并新建一个(如从 relay-bin.000015 切到 relay-bin.000016)。这时如果 relay_log_purge=ON 且旧文件已被 SQL 线程完全应用,就会立刻触发清理。
- 这就是为什么在低流量时段执行
FLUSH LOGS后,发现 relay log 少了一大片——不是命令干的,是“切换 + 自动清理”连招 - 如果 SQL 线程滞后,
FLUSH LOGS后只会新增文件,旧的照常保留 - 在备份脚本里混用
FLUSH LOGS和PURGE RELAY LOGS容易误删:前者触发切换,后者又按名字删,可能把刚切出来还没来得及应用的新文件也干掉
relay_log_purge 关闭后,哪些地方会出问题?
设成 OFF 后,MySQL 彻底放弃自动管理 relay log 生命周期,所有文件永久保留,直到你手动干预。
- 磁盘填满风险极高:主库每秒写 10MB binlog,从库 relay log 也会同步增长,几天就能占几十 GB
-
mysqld启动时仍会读取relay-log.info或 GTID_EXECUTED,但若 relay log 被外部删了,启动直接报错Failed to open the relay log - 使用
CHANGE MASTER TO …… RELAY_LOG_FILE='xxx'手动跳过时,依赖的 relay log 若已被删,复制就断了 - Percona Toolkit 工具如
pt-table-checksum在检测复制延迟时,会扫描 relay log 目录,文件过多会导致超时或误判
实际运维中,最常被忽略的是:**relay log 清理不是独立任务,它和 SQL 线程进度、IO 线程活跃度、以及是否发生过 STOP SLAVE 紧密耦合 **。一次简单的 STOP SLAVE 后忘记 START SLAVE,relay log 就再也不会被自动清理——而错误日志里通常不会报任何警告。