MySQL binlog越积越多因默认不自动清理,需配置binlog_expire_logs_seconds或手动PURGE;误删不可恢复,须提前备份并校验;slow_log和error_log需用logrotate+copytruncate归档。

MySQL的binlog为什么越积越多
默认开启的binlog会持续追加写入,不自动清理。哪怕业务量不大,几个月下来也可能占几十GB——尤其当有大事务、频繁UPDATE或LOAD DATA时,单个binlog文件就可能几百MB。
常见错误现象:SHOW BINARY LOGS;看到上百个文件;磁盘报警但df -h显示/var/lib/mysql目录异常臃肿;备份失败报“no space left on device”。
-
expire_logs_days没设或设为0(MySQL 8.0+已弃用,改用binlog_expire_logs_seconds) - 手动执行过
PURGE BINARY LOGS但没配成定时任务 - 主从复制延迟高,导致从库还没读完的
binlog不敢删
安全清理binlog的三步实操
不能直接rm -f日志文件,MySQL进程还在写,会崩溃。必须走SQL接口或配置驱动。
- 先确认从库同步状态:
SHOW SLAVE STATUS\G,检查Seconds_Behind_Master和Relay_Master_Log_File,确保要删的binlog已被从库读取完毕 - 临时清理:用
PURGE BINARY LOGS TO 'mysql-bin.000123';(删掉指定文件之前的所有日志)或PURGE BINARY LOGS BEFORE '2024-05-01 00:00:00'; - 永久生效:在
my.cnf里加binlog_expire_logs_seconds = 2592000(30天),然后mysqladmin flush-logs重启写入新文件
slow_query_log和error_log怎么压缩归档
这两类日志不支持MySQL内置轮转,得靠外部工具。直接mv或gzip原文件会导致MySQL写失败(它只认固定文件名)。
- 停写再操作:
SET GLOBAL slow_query_log = OFF;→mv+gzip→SET GLOBAL slow_query_log = ON;(注意:部分版本重启后需重设slow_query_log_file) - 更稳妥用
logrotate:配置/etc/logrotate.d/mysql,关键项包括copytruncate(清空原文件而非重命名,避免MySQL丢失句柄)、compress、daily和rotate 7 - 路径别写错:
slow_query_log_file默认是/var/lib/mysql/slow.log,但可能被mysqld_safe覆盖,务必用SELECT @@slow_query_log_file;确认真实路径
误删binlog后还能恢复吗
不能。MySQL不存binlog的校验或快照,删了就是没了。所谓“恢复”,只能靠提前备份的binlog文件或全量备份+后续binlog回放。
- 线上环境务必启用
binlog_checksum = CRC32(MySQL 5.6.2+默认),能早发现文件损坏 - 定期把
binlog同步到另一台机器:rsync -av --delete /var/lib/mysql/mysql-bin.* user@backup:/backup/binlog/,比等出事再抢救靠谱得多 - 如果用了
GTID,删binlog前多看一眼SELECT @@gtid_executed;,避免从库因缺失GTID区间卡住
最常被忽略的是主从场景下PURGE命令的时机判断——不是看时间,而是看SHOW SLAVE STATUS里的Exec_Master_Log_Pos对应哪个binlog文件。差一个文件,从库就再也追不上了。











