安全清理binlog需先确认所有从库Relay_Master_Log_File最小序号(如mysql-bin.000138),以此为界执行PURGE BINARY LOGS TO 'mysql-bin.000138';禁用rm删除,MySQL 8.0+须配置binlog_expire_logs_seconds并配合FLUSH BINARY LOGS释放空间。

先确认所有从库的 Relay_Master_Log_File
主库删 binlog 的安全边界,取决于最慢那个从库同步到了哪。不是看 Master_Log_File(从库自己读到哪个 relay log),而是看 Relay_Master_Log_File(它已成功执行完的主库 binlog 文件名)。登录每台从库,执行:SHOW SLAVE STATUS\G
找到该字段值,比如:Relay_Master_Log_File: mysql-bin.000142
把所有从库的这个值列出来,取其中序号最小的那个(如 mysql-bin.000138)——这就是你能删的“最晚安全线”:所有序号小于它的文件都可删,mysql-bin.000138 本身必须保留。
在主库用 PURGE BINARY LOGS TO 安全删除
绝不能用 rm -f mysql-bin.*,这会破坏 mysql-bin.index、GTID 集和复制位点,导致从库 IO 线程卡死或启动失败。
唯一安全的手动方式是:PURGE BINARY LOGS TO 'mysql-bin.000138';
这条命令会:同步更新索引文件、通知内核释放磁盘句柄、不干扰当前写入的 mysql-bin.000142。
注意:
• 不要用 BEFORE 写法,它依赖文件创建时间戳,易受时区/NTP 偏移影响;
• 执行前务必先在主库运行 SHOW BINARY LOGS;,确认目标文件名存在且不是最旧的;
• 如果某从库 Seconds_Behind_Master 很高,先等它追上,或改用更保守的序号(如 mysql-bin.000139)。
配置 binlog_expire_logs_seconds 并确保自动清理生效
MySQL 8.0+ 中 expire_logs_days 已失效,只起提示作用。真正起效的是:binlog_expire_logs_seconds 和开关 binlog_expire_logs_auto_purge。
检查是否就绪:SHOW GLOBAL VARIABLES LIKE 'binlog_expire_logs_seconds'; → 值应大于 0(如 604800 表示 7 天)SHOW GLOBAL VARIABLES LIKE 'binlog_expire_logs_auto_purge'; → 必须为 ON
设置后不会立刻删文件,MySQL 只在日志轮转(FLUSH BINARY LOGS)、重启或写满时触发扫描。想马上释放空间,设完参数后补一句:FLUSH BINARY LOGS;
删完发现磁盘没释放?检查 lsof 并 FLUSH
执行 PURGE 后 df -h 显示磁盘仍 100%,大概率是 MySQL 进程还持有已删文件的句柄。运行:lsof | grep 'mysql-bin.*deleted'
如果输出一堆类似 mysqld 12345 mysql 12u REG 253,1 1073741824 123456 /var/lib/mysql/mysql-bin.000135 (deleted),说明文件已被逻辑删除但未物理释放。
此时最快解法是:FLUSH BINARY LOGS;
它会强制生成新 binlog(如 mysql-bin.000143),同时让内核真正回收旧文件占用的空间。
lsof 那一步;还有就是把 Relay_Master_Log_File 看成 Master_Log_File,误判从库进度,一删就断复制。


















