必须用purge binary logs命令清理binlog,不可直接rm删除;需逐台检查从库show slave status中的relay_master_log_file,取最大序号文件为安全边界,用to方式精确删除其之前文件,避免误删导致主从中断。

不能直接删文件,必须用 PURGE BINARY LOGS,否则主从立刻中断、报错 Got fatal error 1236——这是最常踩的坑。
怎么确认哪些 binlog 还不能删?
关键不是看主库写了多少,而是看每台从库同步到了哪。漏掉任意一台(尤其是延迟高或临时离线的),就可能删掉它还没读的日志。
- 在每台从库上执行
SHOW SLAVE STATUS\G,只看Relay_Master_Log_File字段(不是Master_Log_File) - 比如三台从库返回分别是
mysql-bin.000135、mysql-bin.000138、mysql-bin.000136,那安全下限就是序号最小的mysql-bin.000135 - 你最多只能执行
PURGE BINARY LOGS TO 'mysql-bin.000136',保留它及之后所有文件 - 主库上先运行
SHOW BINARY LOGS,确认mysql-bin.000136确实存在;输错序号(如写成000134)MySQL 不报错,但会多删一个文件
为什么别用 BEFORE 时间方式清理?
PURGE BINARY LOGS BEFORE '2026-09-25 00:00:00' 看似直观,但依赖 binlog 文件头里的创建时间戳,这个时间可能和系统时间不一致:NTP 偏差、时区配置错误、日志轮转时机都可能导致误删。
-
TO方式按文件名序号精确删除,完全不依赖时间系统,更可靠 - 时间方式在跨时区部署、手动调整过系统时间的服务器上风险极高
- 即使时间配置正确,MySQL 8.0+ 中部分 binlog 文件头时间戳可能为空或异常,
BEFORE会跳过这些文件,导致清理不彻底
清理完 df -h 没变化?那是句柄没关
PURGE BINARY LOGS 执行成功,但磁盘空间没释放,大概率是 Linux 内核还持有已删除文件的句柄。
- 运行
lsof | grep deleted,如果看到大量mysql-bin.* deleted,就证实了这点 - 执行
FLUSH BINARY LOGS触发日志轮转,强制 MySQL 关闭旧句柄(推荐,无中断) - 或者重启 MySQL 服务(更彻底,但有业务中断风险)
- 绝对不要用
rm直接删文件:mysql-bin.index不更新,后续PURGE可能出错,空间也回不来
MySQL 8.0+ 的 expire_logs_days 已被标记为 deprecated,设了也不生效;自动策略只对「非当前正在写的 binlog」生效,已堆积的旧日志不会自动删,得手动 PURGE 一次——这点最容易被忽略。











