实战复盘:从 `Table is full` 到 Binlog 堆积,一次数据采集引发的连环坑排查实录

发布时间:2026/6/3 7:23:37

实战复盘:从 `Table is full` 到 Binlog 堆积,一次数据采集引发的连环坑排查实录 前言蝴蝶效应做数据采集的同学都知道ETL 过程中最怕的不是代码逻辑错误而是环境异常导致的连锁反应。最近我的采集任务就因为一个不起眼的The table is full报错引发了一场惊心动魄的磁盘空间危机。从最初的数据插入失败到试图清空表数据却遭遇建表失败再到慌乱中误删文件最后发现是 Binlog 堆积如山整个过程堪称教科书级别的“踩坑与填坑”。今天就把这次经历整理出来希望能帮大家在遇到类似问题时少走弯路。第一阶段起因——致命的1114报错事情的起因非常简单。我在运行 Python 采集脚本进行数据同步时控制台突然抛出了红色的异常[OperationalError] (pymysql.err.OperationalError) (1114, The table sync_platform_base_sys_attachment is full)看到table is full第一反应通常是“是不是单表数据量太大了或者是磁盘满了”为了尽快恢复业务我决定先清空这张表释放空间后再重新全量拉取。于是我习惯性地执行了TRUNCATETABLEsync_platform_base_sys_attachment;结果依然报错这一次给出了更明确的提示ERROR 3675 (HY000): Create table/tablespace sync_platform_base_sys_attachment failed, as disk is full这时候我才意识到问题的严重性原来磁盘真的已经 100% 满了由于TRUNCATE的底层机制是“销毁旧表并重建一个新空表”在磁盘毫无剩余空间的情况下MySQL 根本无法完成新表的创建动作因此直接宣告失败。为了尽快腾出空间我开始尝试各种“暴力”手段再次尝试DROP TABLE依然不顺畅。甚至慌乱中在 Linux 层面直接rm删除了.ibd数据文件。我以为这样就能把空间腾出来让数据库恢复正常。但现实给了我一记响亮的耳光无论我怎么删表、删文件df -h显示的磁盘占用率依然死死卡在 100%。第二阶段排查——为什么删了文件空间不回来这时候必须冷静下来按步骤排查。1. 检查文件系统缓存File Descriptor当你用rm删除文件时只是删除了目录索引。只要 MySQL 进程还在运行它就握着这个文件的“把手”File Descriptor。操作系统认为文件还在被使用因此不会回收磁盘块。补救措施这种情况下唯一的办法是重启 MySQL 服务。重启后那些被rm掉的.ibd文件占用的空间终于释放了一部分但磁盘依然很满。2. 寻找真正的元凶Binlog重启后我进入/data/mysql/data/目录按大小排序查看文件du-ah/data/mysql/|sort-rh|head-n20结果让我大吃一惊目录下躺着几十个mysql-bin.000xxx文件每个都有 1G 多原来因为我之前的频繁操作包括失败的 TRUNCATE 和 DROPMySQL 记录了大量的二进制日志Binlog。这些日志才是占用几十 G 空间的真凶。第三阶段解决——安全清理 Binlog既然找到了真凶就要安全地清理它。千万不要直接rmBinlog 文件否则会导致主从同步中断或数据库无法启动。1. 确认当前正在写入的日志登录 MySQL执行SHOWMASTERSTATUS;输出显示当前正在写入的是binlog.000044。这意味着000044以及之后的文件是绝对不能动的。2. 执行清理命令我们可以安全地清理掉000043及之前的所有历史日志PURGEBINARYLOGSTObinlog.000044;3. 补充排查如果空间依然没释放怎么办理论上PURGE是一条立即生效的 DDL 操作不需要重启 MySQL 就会自动释放空间。但如果你像我一样之前用过rm命令误删过其他文件或者某些备份工具还在读取旧日志可能会发现执行完PURGE后df -h显示的空间依然没有变化。这是因为 Linux 的文件句柄还没真正关闭。此时你有两个选择推荐做法免重启在 MySQL 中手动触发一次日志刷新FLUSH BINARY LOGS;。这会强制 MySQL 释放对旧日志文件的句柄引用空间会瞬间真实归还给操作系统。备选做法如果业务允许停机直接systemctl restart mysqld重启服务也能彻底释放残留句柄。在我的操作中执行完FLUSH BINARY LOGS;后再次运行df -h磁盘空间瞬间释放了 40G采集任务也终于能正常插入了。总结与反思这次故障虽然解决了但留下了深刻的教训遇到Table is full先查磁盘不要盲目操作数据库先用df -h确认服务器状态。严禁rm数据库文件Linux 的文件句柄机制决定了直接删除文件无法释放空间反而可能导致数据丢失或空间假死。配置 Binlog 自动过期为了避免未来再次发生此类问题建议在my.cnf中配置自动清理策略[mysqld] binlog_expire_logs_seconds 604800 # 保留7天希望这篇复盘能帮到大家如果你在数据采集或运维中遇到过类似的问题欢迎在评论区交流

相关新闻