唯一安全解法是重建从库;防错核心是只删从库已确认消费的binlog,须逐台查relay_master_log_file,purge前确认最老binlog不早于所有从库进度,禁用reset master,用binlog_expire_logs_seconds控制自动清理,并配合os权限管控与归档。

主库 binlog 被提前清理,从库就必然断档,且无法续传——这不是延迟问题,是物理日志缺失导致的不可逆复制中断。唯一安全解法是重建从库,代价远高于预防。防错核心不是“别删”,而是“只删从库已确认消费过的部分”。
查清所有从库同步到哪个 binlog 文件
必须登录每台从库执行 SHOW SLAVE STATUS\G,重点看 Relay_Master_Log_File(不是 Master_Log_File),它代表该从库已成功执行完的主库日志文件名。例如返回:Relay_Master_Log_File: mysql-bin.000138
说明这台从库已处理完 mysql-bin.000138 及之前所有日志。
- 多从库环境必须逐个检查,不能只看其中一台
- 若某从库
Slave_IO_Running: No,先恢复同步再查,否则它的Relay_Master_Log_File是过期值 - GTID 模式下仍要查此项,
Executed_Gtid_Set不能替代文件名判断(因 purged GTID 可能不连续)
PURGE 命令前必须确认主库当前最老 binlog
登录主库后,先执行 SHOW BINARY LOGS; 查看现存日志列表,找出序号最小的文件(如 mysql-bin.000135)。这个文件必须 ≥ 所有从库中 Relay_Master_Log_File 的最小序号,否则说明已有从库落后于当前最老日志,此时禁止任何 PURGE。
- 若最老文件是
mysql-bin.000135,而某从库停在mysql-bin.000134,说明它还没追上——必须等它追平或先人工干预 -
PURGE BINARY LOGS TO 'mysql-bin.000136';实际删除的是.000135及更早的,保留.000136起全部 - 严禁用
RESET MASTER,它会清空所有 binlog 并重置序列,直接导致所有从库失效
自动清理必须用 binlog_expire_logs_seconds,且设足够长
MySQL 8.0+ 中 expire_logs_days 已弃用,仅靠它无法生效。真正起作用的是 binlog_expire_logs_seconds,默认 2592000 秒(30 天),但生产环境建议设为 604800(7 天)并确保 binlog_expire_logs_auto_purge = ON。
- 临时设置:
SET GLOBAL binlog_expire_logs_seconds = 604800;,但需写入my.cnf的[mysqld]段才持久 - 云数据库(如阿里云 RDS)通常禁用该变量,必须在控制台调整“Binlog 保留天数”,且修改后需重启复制链路
- 若磁盘空间紧张触发自动 purge,MySQL 会优先删最老日志——这意味着你设的保留时间可能被绕过,必须配合磁盘监控(df -h /var/lib/mysql > 85% 时告警)
操作系统层加保护,防误删和越权操作
即使配置正确,人为 rm 或低权限账号执行 PURGE 仍可能导致灾难。应在 OS 层限制 binlog 目录写权限,并回收危险权限。
- 将 binlog 存储目录(如
/var/lib/mysql/logs/)所有权设为root:mysql,权限750,仅允许 MySQL 进程追加,禁止删除 - 撤销普通应用账号的
REPLICATION CLIENT和SUPER权限,防止其执行PURGE或RESET MASTER - 定期归档:用脚本调用
mysqlbinlog导出旧日志为 SQL 或压缩包,再安全删除原始文件——注意归档链必须完整(从最早 active 日志到当前)
最容易被忽略的是:PURGE 后 df -h 看不到磁盘释放,其实是 MySQL 进程还持有已删文件句柄。此时必须执行 FLUSH BINARY LOGS; 触发轮转,内核才会真正释放空间。不处理这点,清理就等于白做。











