必须用purge binary logs或配置binlog_expire_logs_seconds自动清理,严禁rm删除;操作前须确认log_bin=on、从库relay_master_log_file位置,并在mysql 8.0+中禁用expire_logs_days、启用binlog_expire_logs_seconds。

直接删 mysql-bin.* 文件会断主从、丢数据,必须用 PURGE BINARY LOGS 或配自动策略——但前提是确认从库已同步完你要删的日志。
先查清楚:binlog 真的在涨?还是根本没开?
别急着删,很多“暴涨”其实是误判。先连上 MySQL 执行:
-
SHOW VARIABLES LIKE 'log_bin';—— 返回ON才说明 binlog 确实开着;如果OFF,那磁盘占满跟 binlog 无关 -
SHOW BINARY LOGS;—— 看文件数量和总大小,File_size加起来超 2GB 就该干预了 -
SHOW MASTER STATUS;—— 记下当前正在写的文件名(如mysql-bin.000142),这是安全删除的上限
主从环境下,怎么知道哪些 binlog 能删?
关键不是“主库写了啥”,而是“从库读到哪”。每台从库都要查:
- 登录从库,执行
SHOW SLAVE STATUS\G; - 重点看
Relay_Master_Log_File字段(不是Master_Log_File)——它表示该从库已执行完的主库日志文件名 - 找出所有从库中
Relay_Master_Log_File序号最小的那个(比如mysql-bin.000135),这就是安全下限:你最多只能PURGE TO 'mysql-bin.000136';
漏掉任意一台从库,删掉它还没读的日志,Slave_IO_Running 立刻变 No,报错 Got fatal error 1236。
MySQL 8.0+ 必须用 binlog_expire_logs_seconds,expire_logs_days 已失效
MySQL 8.0 开始,expire_logs_days 参数被标记为 deprecated,设了也不生效。强行配置可能白忙活:
- 临时生效:
SET GLOBAL binlog_expire_logs_seconds = 604800;(7 天),同时清掉旧参数:SET GLOBAL expire_logs_days = 0; - 永久生效:编辑
my.cnf的[mysqld]段,加两行:binlog_expire_logs_seconds = 604800expire_logs_days = 0 - 重启后验证:
SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';必须返回你设的值
注意:自动策略只对「非当前正在写的 binlog」生效,已堆积的旧日志不会自动删,得手动 PURGE 一次。
清理后磁盘空间没释放?大概率是文件句柄没关
PURGE BINARY LOGS 执行成功,df -h 却没变化,不是命令失败,而是 Linux 内核还在保留已删除文件的句柄:
- 运行
lsof | grep deleted,如果看到大量mysql-bin.* deleted,就证实了这点 - 最稳妥解法:执行
FLUSH BINARY LOGS;(触发日志轮转),或重启 MySQL 服务 - 别用
rm直接删文件——MySQL 进程仍持有句柄,df不认,du却还统计,空间就是不回来
真正释放空间的关键不在“删”,而在“让 MySQL 放手”。











