磁盘写满时MySQL卡住应优先清理binlog而非重启,再检查大文件、关闭日志等;ibdata1在innodb_file_per_table=OFF时无法收缩,需导出重建。

磁盘写满时,mysql 进程卡住或拒绝写入,先别重启
MySQL 在磁盘满时不会自动清理日志或释放空间,而是直接报错、挂起写操作,甚至让 INSERT、UPDATE、CREATE TABLE 返回 ERROR 1030 (HY000): Got error 28 from storage engine。这时候强行重启可能让 InnoDB 崩溃恢复变复杂,尤其没开 innodb_fast_shutdown=0 时。
优先做三件事:
- 确认哪个分区满了:
df -h看/var/lib/mysql所在挂载点 - 快速定位大文件:
du -sh /var/lib/mysql/* | sort -hr | head -5 - 检查是否是
ib_logfile0/1或slow_query_log、general_log疯长 —— 这些不关掉会持续写入
清理 binlog 是最快见效的空间释放手段
主从环境或开了 log_bin 的实例,binlog 文件常占几十 GB 且长期不清理。它不随 MySQL 重启消失,必须主动 purge。
操作前确认两点:
- 所有从库已同步到哪个
binlog文件(查SHOW SLAVE STATUS\G中的Relay_Master_Log_File) - 本地备份是否依赖这些日志(如用
mysqlbinlog做 PITR)
安全清理命令:
PURGE BINARY LOGS TO 'mysql-bin.000123';
或按时间删(比如保留最近 3 天):
PURGE BINARY LOGS BEFORE '2024-04-01 00:00:00';
注意:PURGE 不释放文件系统 inode,但会删物理文件;如果 binlog 被其他进程(如 mysqldump --master-data 长连)占用,可能删不掉 —— 此时得先 kill 掉对应线程。
innodb_file_per_table=OFF 时,ibdata1 只增不减
老配置下所有表数据都挤进共享表空间 ibdata1,删库、删表、OPTIMIZE TABLE 都不会缩小它。你看到 df 没变化,不是 MySQL 没干活,是空间根本没还给文件系统。
唯一能回收的方式是导出 + 重建:
- 用
mysqldump导出全部数据库(不含information_schema) - 停 MySQL,删掉
/var/lib/mysql/ibdata1、ib_logfile*、ibtmp1 - 改配置:确保
innodb_file_per_table=ON,再启动 —— 它会新建更小的ibdata1(仅存元数据) - 导入 dump
风险点:innodb_file_per_table=OFF 下的 TRUNCATE TABLE 仍会增长 ibdata1;且迁移过程需停机,线上慎用。
临时腾空间:关日志、清临时文件、删无用库
救急场景下,立刻释放几 GB 是可行的,但每项都有副作用:
- 关慢日志:
SET GLOBAL slow_query_log = OFF;,再删/var/lib/mysql/*.log(前提是没被 mysqld 占用) - 清
tmpdir下残留临时表:ls -lt /tmp/ | grep -i mysql,手动rm(注意别删正在用的ibtmp1) - 删测试库:
DROP DATABASE test_db;—— 但 InnoDB 表空间不会立即释放,要等innodb_file_per_table=ON才行 - 禁用
general_log:SET GLOBAL general_log = OFF;,然后删对应日志文件
最易被忽略的是:MySQL 启动时若 log_error 指向的错误日志路径满了,连 mysqld 都起不来 —— 此时得先 mv /var/log/mysql/error.log /tmp/ 之类腾地方。


















