根本原因是expire_logs_days未设置或为0导致binlog永不自动清理;MySQL 5.7用expire_logs_days,8.0+改用binlog_expire_logs_seconds;手动PURGE前须核对主从位置,避免复制中断。

MySQL 安装后 binlog 占用空间过大,根本原因通常是 expire_logs_days 未设置或设为 0 —— 这意味着 binlog 永不自动删除。
为什么 expire_logs_days=0 就会爆满?
MySQL 默认值是 expire_logs_days = 0,官方明确表示该值代表“不启用自动清理”。哪怕你只跑一个 INSERT 循环,只要 binlog 开启(log-bin 已配置),日志就会持续追加、滚动、累积,直到磁盘写满。尤其在 RDS 或云数据库中,这常直接触发实例锁定(状态变为“锁定中”)。
- 每次
FLUSH LOGS或日志大小达到max_binlog_size,都会生成新文件(如mysql-bin.000001→mysql-bin.000002) - 但旧文件不会被删,除非你显式设置了
expire_logs_days > 0且满足触发条件(比如每日定时轮转时检查) - 注意:这个参数只在 MySQL 启动后或日志刷新时才真正执行清理,不是实时监控
MySQL 5.7 和 8.0 的配置差异必须看清
MySQL 8.0+ 已弃用 expire_logs_days,改用 binlog_expire_logs_seconds;两者不能共存,否则启动报错 3683。
- MySQL 5.7:可安全使用
expire_logs_days = 7(单位:天) - MySQL 8.0:必须用
binlog_expire_logs_seconds = 604800(7 天 = 604800 秒) - 修改方式:优先写进
my.cnf的[mysqld]段并重启;若需临时生效,用SET GLOBAL,但要注意权限和主从一致性
PURGE 命令手动清理前,必须确认主从位置
直接 PURGE BINARY LOGS BEFORE '2026-05-01' 很快,但极可能破坏主从复制——如果从库还没读完你要删的那部分日志,就会报错 Got fatal error 1236。
- 查主库当前日志:
SHOW MASTER STATUS→ 记下File字段(如mysql-bin.000123) - 查从库延迟:
SHOW SLAVE STATUS\G→ 看Relay_Master_Log_File和Exec_Master_Log_Pos - 安全删除范围:只能删
mysql-bin.000122及更早的;不能删mysql-bin.000123及之后的 - 命令示例:
PURGE BINARY LOGS TO 'mysql-bin.000123'(保留该文件及之后所有)
大事务会让 binlog 突然远超 max_binlog_size
max_binlog_size = 1G 并非硬限制。一个 5GB 的 UPDATE 事务,MySQL 仍会把它完整写进单个 binlog 文件(比如 mysql-bin.000123 达到 5.2G),因为事务不可拆分。
- 这种场景下,
expire_logs_days依然有效,但你得先扛过单文件暴涨阶段 - 临时缓解:用
SET SESSION sql_log_bin = 0关闭当前会话 binlog(仅限非生产调试) - 长期解法:业务层拆分大事务,每 1000 行
COMMIT一次,避免单事务撑爆日志 - 切记:
SET GLOBAL sql_log_bin = 0会全局停写 binlog,主从立刻中断,绝对禁止
最易被忽略的一点:即使你正确设置了 expire_logs_days 或 binlog_expire_logs_seconds,历史 binlog 不会“立刻消失”。它只在下次日志轮转(如重启、FLUSH LOGS、或达到 max_binlog_size)时才触发清理逻辑。所以看到磁盘没马上释放,别慌,先等一轮日志滚动。


















