relay_log写满磁盘会导致sql线程报错退出、复制彻底中断;根本原因是其默认与datadir共用分区且不受expire_logs_days控制,仅依赖relay_log_purge=on和sql线程进度清理,一旦线程停滞即堆积失控。

relay_log 写满磁盘不是“延迟高”,是 SQL 线程直接退出、复制彻底中断——必须立刻停 SQL 线程并迁移路径,不能只靠 PURGE 或删文件。
为什么 relay_log 满了会卡死,而 expire_logs_days 完全无效
因为 relay_log 不受 expire_logs_days 控制,它只依赖 relay_log_purge=ON(默认开启)和 SQL 线程的消费进度。一旦 SQL 线程因错误、大事务或锁冲突停住,relay_log 就不再被清理,文件持续堆积。更关键的是:它默认和 datadir 共用同一分区,主库持续写入 + 从库消费慢 → 磁盘瞬间打满。错误日志里常见:ERROR 1594 (HY000): Relay log read failure 或操作系统级报错:OS error code 28: No space left on device。
紧急止血:停 SQL 线程 + 手动清理旧 relay_log 文件(需确认无风险)
仅当 Slave_SQL_Running: Yes 且 Seconds_Behind_Master 很小(比如
- 先执行
STOP SLAVE SQL_THREAD;,避免新事件继续写入 - 查当前正在用的 relay log:
SHOW SLAVE STATUS\G中看Relay_Log_File和Relay_Log_Pos - 进
datadir目录,用ls -lt mysql-relay-bin.*排序,把比Relay_Log_File更老的文件(注意文件名编号顺序)全部rm—— 切勿删正在用的那个,也别碰mysql-relay-bin.index - 再执行
START SLAVE SQL_THREAD;,观察是否恢复;若仍报错或卡住,说明已有损坏,需走完整迁移流程
根治方案:把 relay_log 和 relay_log_index 迁到独立挂载点
这是唯一长期可靠的方式。迁移不是“改配置重启”那么简单,操作顺序错一步,MySQL 启动后可能找不到索引或拒绝启动。
- 执行
STOP SLAVE;,确认Seconds_Behind_Master = 0或已追平 - 记下
Relay_Master_Log_File和Exec_Master_Log_Pos(后续验证数据一致性用) - 新建目录,如
/data/relaylog,确保属主为mysql、权限750;不要拷旧文件过去 - 在
my.cnf的[mysqld]段添加两行:relay_log = /data/relaylog/mysql-relay-bin,relay_log_index = /data/relaylog/mysql-relay-bin.index - 重启
mysqld,启动成功后立刻START SLAVE;,再用SHOW SLAVE STATUS\G确认两个线程都为Yes
别碰 ibdata1 和 ib_logfile*,除非你准备好停库重建
磁盘满时最容易手抖去删这些文件——但 ibdata1 在 innodb_file_per_table=OFF 下永不收缩,删了等于删库;ib_logfile0/1 是 redo log,MySQL 启动时校验大小,删了会导致启动失败,报错类似:InnoDB: Error: log file ./ib_logfile0 is of different size。它们只能在停库后按规范流程替换,不能在线清理。
真正容易被忽略的点是:监控必须拆开看——datadir 使用率 ≠ relay_log 所在路径使用率。很多告警只盯 df -h 根分区,却漏掉 /data/relaylog 单独挂载的小分区。上线前务必确认 relay_log 路径有独立磁盘、预留至少 20% 空间,并加入 zabbix 或 Prometheus 的专项监控项。











