error 3或os error code 28是磁盘写入失败信号,需先用df -h /backup和df -i确认空间及inodes余量,检查/tmp是否与备份路径同分区,可加--tmpdir指定大空间临时目录,并在备份前添加空间校验脚本防止半截失败。

备份时提示 ERROR 3 或 OS error code 28: No space left on device
这是磁盘写入失败的典型信号,不是 MySQL 自身报错,而是操作系统拒绝了 mysqldump 或 xtrabackup 的文件写入请求。此时备份进程直接中断,且不会自动重试或降级——它就卡在那儿,等你手动清理。
实操建议:
- 先用
df -h /backup(或你的备份目标路径)确认实际剩余空间,注意Inodes也可能耗尽(df -i),尤其当小文件极多时 - 检查
/tmp目录是否和备份路径同分区——mysqldump默认用/tmp做临时缓冲,大表导出会先落盘再压缩,容易爆掉 - 临时救急可加
--tmpdir=/path/to/larger/disk指定临时目录,但只是绕过,不解决根本问题
用 du -sh /var/lib/mysql/* 快速定位膨胀源
很多团队只盯着 ibdata1 或日志,却忽略真正吃空间的是慢查询日志、general log、或者残留的 binlog 归档。MySQL 本身不自动清理这些,全靠人工或外部脚本。
实操建议:
- 查开启状态:
SHOW VARIABLES LIKE 'general_log%';和SHOW VARIABLES LIKE 'slow_query_log%';,关闭不用的日志能立刻释放 GB 级空间 - 查 binlog 占用:
SHOW BINARY LOGS;,再结合expire_logs_days设置(默认 0,即永不过期);设成7是较安全的起点 -
innodb_file_per_table=ON是前提,否则单表删数据不缩表空间,OPTIMIZE TABLE也无效
备份前加空间校验脚本,别依赖定时任务“准时跑”
备份失败后才发现空间不够,说明监控是滞后的。真正的防御是让备份命令自己判断:不够就不启动,避免半截失败还留一堆临时文件。
实操建议:
- 在调用
mysqldump前插入一行:[ $(df --output=avail /backup | tail -1) -lt 5242880 ] && echo "NOT ENOUGH SPACE" && exit 1(单位 KB,这里指至少 5GB) - 如果用
xbbackup,它本身不带空间预检,必须在外层 shell 封装;注意--parallel越高,临时空间峰值越大,阈值要相应上浮 - 报警不能只发邮件——要触发钉钉/企微机器人,并带上
df -h和ls -lh /backup/最新结果,省得运维再连一次机器
information_schema.TABLES 查表大小不准,但它是唯一能快速估算的入口
DATA_LENGTH + INDEX_LENGTH 是 InnoDB 引擎估算值,和 du -sh 物理大小常差 20%–30%,因为没算 undo、change buffer、碎片等。但它快,适合做阈值粗筛。
实操建议:
- 查 Top 10 大表:
SELECT TABLE_SCHEMA, TABLE_NAME, ROUND((DATA_LENGTH+INDEX_LENGTH)/1024/1024, 2) AS MB FROM information_schema.TABLES ORDER BY MB DESC LIMIT 10; - 别信
AVG_ROW_LENGTH × TABLE_ROWS,这个值长期不更新,ANALYZE TABLE才会刷新,但代价高,生产环境慎用 - 真正要缩空间,得看
innodb_file_per_table下单表.ibd文件大小,OPTIMIZE TABLE后再ls -lh对比才准
空间报警的复杂点不在阈值设多少,而在于不同实例的备份行为差异太大:有的压 gzip,有的用 pigz,有的开 --compress,有的走流式加密。同一套脚本,在 A 实例剩 10GB 能过,在 B 实例可能卡在 15GB 就失败。得按实例配单独策略,而不是全局一刀切。











