必须先确认中继日志使用状态再清理:通过show slave status查看relay_log_file、relay_master_log_file和exec_master_log_pos,仅删除已执行完毕的旧文件;复制异常时禁止清理;推荐用reset slave安全释放空间。

从库磁盘满,**别直接删 relay-log.* 文件**——90% 的复制中断和启动失败都源于这一步。真正安全、可落地的清理动作只有两个:确认状态后用 RESET SLAVE,或长期启用 relay_log_purge = ON 防复发。
怎么判断哪些中继日志能删?看 SHOW SLAVE STATUS\G 里的三个字段
执行命令后重点盯住:
-
Relay_Log_File:当前正在写的中继日志名(比如mysql-relay-bin.000456),它和它前面 1–2 个文件是活跃的,绝不能动 -
Relay_Master_Log_File和Exec_Master_Log_Pos:合起来表示“SQL 线程已执行到主库哪个 binlog 的哪个位置”。所有relay-log.*中,文件序号小于Relay_Master_Log_File且内容已全部执行过的,才可清理 -
Seconds_Behind_Master是NULL或远大于 0?说明复制异常,此时禁止任何清理操作
用 RESET SLAVE 清理比手动 rm 安全得多
RESET SLAVE 不是“重启复制”,而是让 MySQL 自动清空已过期的中继日志,并重置本地坐标(Relay_Log_File、Relay_Log_Pos),但保留主库连接信息(MASTER_HOST 等)。
- 执行前确保
Seconds_Behind_Master = 0且Slave_IO_Running = Yes、Slave_SQL_Running = Yes - 执行后必须手动运行
START SLAVE,否则复制不会恢复 - 不要用
RESET SLAVE ALL,除非你准备重建整个从库——它会清空所有主库配置,后续必须重新CHANGE MASTER TO -
FLUSH LOGS对中继日志完全无效,别被网上教程带偏
为什么中继日志越积越多?大概率是 relay_log_purge 被关了
MySQL 默认开启 relay_log_purge = ON,意思是 SQL 线程一执行完某段中继日志,就自动删除它。如果发现日志长期不释放,先查这个变量:
SHOW VARIABLES LIKE 'relay_log_purge';
- 输出是
OFF?立刻设回:SET GLOBAL relay_log_purge = ON; - 该变量动态生效,无需重启;但若配置文件里写了
relay_log_purge = OFF,记得同步注释掉,否则重启后又失效 - 延迟高的从库(
Seconds_Behind_Master很大)即使ON也会暂存日志,这是正常行为,不是 bug
实在没空间了,临时迁移 datadir 比硬删更可控
当 /var/lib/mysql 所在分区彻底写满,连 RESET SLAVE 都执行不了时,迁移数据目录是更稳妥的选择:
- 先停服务:
systemctl stop mysqld(或service mysql stop) - 把整个
/var/lib/mysql拷到空间充足的路径,比如/data/mysql:rsync -av /var/lib/mysql/ /data/mysql/ - 修改
my.cnf中的datadir = /data/mysql,并确保chown -R mysql:mysql /data/mysql - 启动前检查 SELinux 是否拦截(
ls -Z /data/mysql),必要时用semanage fcontext修复上下文 - 不推荐软链接方案——某些 MySQL 版本对符号链接支持不稳定,容易在崩溃恢复时出错
最常被忽略的其实是 relay_log_purge 的状态和复制是否真正追平。很多 DBA 看到 Seconds_Behind_Master = 0 就以为安全,却没注意 Slave_SQL_Running_State 是 “Reading event from the relay log” 还是 “System lock” —— 后者可能意味着 SQL 线程卡在某个大事务里,中继日志仍在堆积。











