直接删 mysql-bin.* 文件会崩库,因其被 mysql-bin.index 索引统一管理,手动删除会导致索引与实际文件不一致,引发 mysql 启动失败、主从中断或写入中断;唯一安全方式是使用 purge binary logs 命令,它同步更新索引并通知复制线程。

为什么直接删 mysql-bin.* 文件会崩库
MySQL 的 mysql-bin.* 文件不是普通日志,它被 mysql-bin.index 索引文件统一管理,且主从复制、备份恢复都依赖这个链路。你用 rm -f mysql-bin.000123 这类系统命令硬删,MySQL 完全不知情:索引里还记着它、从库可能正读它、SHOW BINARY LOGS 仍显示它——结果是主从中断、RESET MASTER 失败、甚至 mysqld 启动报错。唯一合法入口只有 PURGE BINARY LOGS,它会同步更新索引、通知复制线程、触发磁盘释放。
PURGE BINARY LOGS TO 和 BEFORE 的实际差异
选错语法等于误删,必须分清:
-
PURGE BINARY LOGS TO 'mysql-bin.000200':只删序号 小于 000200 的所有文件(即 000001~000199),000200 及之后全部保留。逻辑确定、不依赖系统时间,推荐首选。 -
PURGE BINARY LOGS BEFORE '2026-09-01 00:00:00':删的是文件系统里mtime或 binlog 头部记录的“创建时间”早于该时刻的文件。但这个时间戳可能和你执行FLUSH LOGS的时机有关,NTP 偏差、时区设置、从库延迟都会导致误判——比如明明想删 30 天前的,结果把刚轮转出来的 000199 也删了。
主从架构下怎么确认能安全删到哪
不能只看主库 SHOW MASTER STATUS 的 File(那是当前正在写的,肯定不能删),关键要看所有从库是否已消费完毕:
- 在每个从库上执行
SHOW REPLICA STATUS\G(MySQL 8.0.22+)或SHOW SLAVE STATUS\G(旧版),记下Relay_Master_Log_File字段值,例如mysql-bin.000185、mysql-bin.000192、mysql-bin.000177 - 取这些文件名中序号最大的那个(这里是
000192),这就是安全边界——你最多只能PURGE TO 'mysql-bin.000193',确保000192及更早的都被保留 - 如果某从库
Seconds_Behind_Master很高(比如 > 3600),先等它追上,或临时调大binlog_expire_logs_seconds避免自动清理干扰
执行前必须做的三件事
跳过任何一步都可能引发线上事故:
- 确认权限:当前用户必须有
BINLOG_ADMIN权限,否则报错ERROR 1227 (42501): Access denied - 查现状:
SHOW BINARY LOGS;输出当前所有 binlog 文件列表,核对你要TO的文件名是否存在、序号是否输错(比如把000193写成00019) - 留证:
mysqldump或cp备份一份mysql-bin.index和目标删除范围内的文件(如mysql-bin.000001到000192),放在其他磁盘,防误操作回滚
真正危险的不是命令本身,而是你以为删的是“旧文件”,其实删的是从库还没读完的“活日志”。序号比时间靠谱,最大序号比单个从库状态靠谱,备份比后悔靠谱。











