1236错误本质是主库缺失从库请求的binlog文件或位点,修复需先确认主库是否已删除对应binlog(用show binary logs比对),再根据gtid或传统模式选择重设位点、合并gtid_purged或重建同步。

必须先确认所有从库已同步到目标日志,否则 PURGE BINARY LOGS 会直接断主从——Slave_IO_Running 立刻变 No,报错 Got fatal error 1236。
查清主库当前写入位置和从库同步边界
主库上执行 SHOW MASTER STATUS,记下 File 字段(如 mysql-bin.000142),这是正在写的文件,绝对不能删。
每台从库单独执行 SHOW SLAVE STATUS\G,只看 Relay_Master_Log_File(不是 Master_Log_File),它代表该从库已执行完的主库日志名。比如三台从库返回分别是:mysql-bin.000135、mysql-bin.000138、mysql-bin.000136,那安全下限就是序号最小的那个:mysql-bin.000135 ——你最多只能 PURGE TO 'mysql-bin.000136',保留它及之后的所有文件。
漏掉任意一台从库(尤其是延迟高或临时离线的),就可能删掉它还没读的日志。
用 PURGE BINARY LOGS TO 而不是 BEFORE
PURGE BINARY LOGS BEFORE '2026-09-25 00:00:00' 看似直观,但实际依赖 binlog 文件头里的创建时间戳,这个时间可能和系统时间不一致,NTP 同步偏差、时区配置错误都会导致误删。
PURGE BINARY LOGS TO 'mysql-bin.000136' 更可靠:它按文件名序号精确删除所有更旧的文件(000001 到 000135),000136 本身保留,完全不依赖时间系统。
注意:TO 后面的文件名必须存在于 SHOW BINARY LOGS 结果中;如果输错序号(比如写成 000134),MySQL 不报错,但会多删一个文件。
清理后磁盘空间没释放?检查文件句柄是否残留
PURGE BINARY LOGS 执行成功,df -h 却没变化,大概率是 Linux 内核还持有已删除文件的句柄。
运行 lsof | grep deleted,如果看到大量 mysql-bin.* deleted,就证实了这点。
两个解法:
- 执行
FLUSH BINARY LOGS(触发日志轮转,强制 MySQL 关闭旧句柄) - 或者重启 MySQL 服务(更彻底,但有业务中断风险)
别用 rm 直接删文件——mysql-bin.index 不更新,MySQL 还以为那些日志存在,后续 PURGE 可能出错,而且空间照样不回来。
MySQL 8.0+ 必须用 binlog_expire_logs_seconds
expire_logs_days 在 MySQL 8.0+ 已被标记为 deprecated,设了也不生效。强行配了还可能干扰判断。
永久生效要改 my.cnf:
binlog_expire_logs_seconds = 604800 expire_logs_days = 0
然后执行 SET GLOBAL binlog_expire_logs_seconds = 604800 动态加载。验证是否生效:SHOW VARIABLES LIKE 'binlog_expire_logs_seconds' 必须返回你设的值。
注意:自动策略只对「非当前正在写的 binlog」生效;已堆积的旧日志不会自动删,得手动 PURGE 一次。
最易忽略的一点:自动清理不等于“实时清理”。即使配了 binlog_expire_logs_seconds,如果业务写入极低,binlog 文件长期不翻页(max_binlog_size 没达到),过期日志就一直堆着不动——得靠 FLUSH BINARY LOGS 或定期手动 PURGE 触发清理逻辑。











