必须设binlog_expire_logs_seconds,否则mysql 8.0默认值为0(永不清除);需先查log_bin=on、binlog_expire_logs_seconds非零且binlog_expire_logs_auto_purge=on才生效,配置仅管控新日志,旧日志须手动purge并配合flush logs释放句柄。

必须设 binlog_expire_logs_seconds,否则 binlog 永远不删——MySQL 8.0 默认值是 0,等同于永久保留。
确认 binlog 是否开启及当前过期策略
别信配置文件里写了什么,先查真实状态。很多“磁盘满了”问题其实根本没开 binlog,或者开了但参数压根没生效:
- 运行
mysql -uroot -p -e "SHOW VARIABLES LIKE 'log_bin';",返回ON才说明已启用 - 执行
SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';,若值为0或空,代表未启用自动清理 - 用
SHOW BINARY LOGS;看文件数量和总大小,File_size列加起来超 2GB 就该动手了 - 顺手查
SHOW VARIABLES LIKE 'binlog_expire_logs_auto_purge';,必须是ON,否则设了秒数也无效
MySQL 8.0 必须用 binlog_expire_logs_seconds
expire_logs_days 在 MySQL 8.0 已废弃,设了也不生效,还可能触发 ERROR 3683。强行写进配置或 SET GLOBAL 都白忙活:
- 7 天对应秒数是
604800,临时设置:SET GLOBAL binlog_expire_logs_seconds = 604800; - 为防冲突,同步清掉旧参数:
SET GLOBAL expire_logs_days = 0; - 编辑配置文件(宝塔路径是
/www/server/mysql/etc/my.cnf,通用路径是/etc/mysql/mysql.conf.d/mysqld.cnf),在[mysqld]段末尾添加:binlog_expire_logs_seconds = 604800<br>expire_logs_days = 0
- 保存后重启:
systemctl restart mysqld,再查SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';确认值是你设的
手动 PURGE 前必须核对主从位置
配置只管新日志,已堆积的几十个 mysql-bin.000xxx 不会自动消失。误删会断主从——删掉从库还没读的日志,Slave_IO_Running 立刻变 No,报错 Got fatal error 1236:
- 主库执行
SHOW MASTER STATUS;,记下当前File(如mysql-bin.000042) - 每台从库执行
SHOW SLAVE STATUS\G,看Relay_Master_Log_File字段 - 找出所有从库中序号最小的那个文件(比如
mysql-bin.000035),这就是安全底线 - 执行
PURGE BINARY LOGS TO 'mysql-bin.000036';(删掉该文件之前所有) - 清理后空间没释放?大概率是文件句柄没关,补一句
FLUSH LOGS;
大事务和 binlog_format 是隐藏爆点
单个事务写几 GB binlog,不是配置没设好,而是应用层在“制造炸弹”:
-
ROW格式下一条UPDATE可能生成百万级 event;STATEMENT模式就只有 1 条。先查SHOW VARIABLES LIKE 'binlog_format'; - 非必要场景建议切到
MIXED:自动降级为STATEMENT,仅在必要时用ROW - 调大
binlog_cache_size(如设为4194304)只是缓解,不是根治;真正要做的,是识别谁在疯狂产 binlog - 检查
SHOW STATUS LIKE 'binlog_cache%';,若binlog_cache_disk_use接近binlog_cache_use,说明几乎每个事务都在刷盘
配置生效、旧日志清完、格式调妥,三者缺一不可。最容易被忽略的是:清理后不执行 FLUSH LOGS,磁盘空间依然不释放——因为 MySQL 还拿着旧文件句柄没放。











