磁盘爆满时MySQL写入被内核阻塞,未提交事务数据仅存内存或临时文件,无法被备份工具读取;可抢救的仅有已提交未刷盘数据(靠redo log恢复)和长事务修改行(需通过INNODB_TRX定位);首要操作是释放空间、恢复MySQL响应能力,再执行FLUSH LOGS和完整逻辑备份。

磁盘空间爆满时,mysqldump、SELECT INTO OUTFILE 或任何需要写入磁盘的操作都会失败——不是因为数据丢了,而是 MySQL 已被内核阻塞写入,连 SHOW PROCESSLIST 都卡在 Writing to net 状态。此时谈“备份未提交数据”本身是个伪命题:事务未提交的数据只存在于内存(innodb_buffer_pool)或临时文件(ibtmp1),根本没落盘,也**无法被外部工具直接读取**。
先确认哪些数据还“活着”
未提交事务里的数据,MySQL 自己都还没决定要不要写,更不会暴露给备份工具。能抢救的只有两类:
- 已提交但尚未刷盘到
ibdata1或.ibd的数据:靠崩溃恢复机制自动回放redo log,不用你手动备份 - 正在运行的长事务(
TRX_STATE = 'RUNNING')里修改过的行:这部分可查information_schema.INNODB_TRX和INNODB_LOCK_WAITS定位,但内容本身不可导出
执行这个检查:
SELECT trx_id, trx_state, trx_started, trx_mysql_thread_id,
SUBSTRING_INDEX(trx_query, ' ', 10) AS brief_query
FROM information_schema.INNODB_TRX
WHERE TIME_TO_SEC(TIMEDIFF(NOW(), trx_started)) > 60;
如果有结果,说明有活跃长事务——它正把 ibtmp1 或 tmpdir 帐户撑大,但它的 SQL 语句本身不等于“可备份的数据”。
真正该做的:释放空间,让 MySQL 恢复写能力
备份的前提是 MySQL 能正常响应。别碰 mysqldump,先解决阻塞根源:
- 用
df -h /var/lib/mysql /tmp /var/log找出 >95% 的挂载点 - 查
SHOW VARIABLES LIKE 'datadir';和SHOW VARIABLES LIKE 'tmpdir';,确认路径归属 - 若
/tmp满了(尤其 CentOS 默认tmpfs),立刻清空/tmp下非关键临时文件,或改tmpdir到其他分区:SET GLOBAL tmpdir='/path/to/larger/partition'; - 若 binlog 占满,必须先验证从库状态再
PURGE BINARY LOGS TO 'mysql-bin.000xxx';,严禁rm -f - 若
ibtmp1膨胀严重(5.7.30+),且无长事务,执行ALTER TABLESPACE innodb_temp_tablespaces ENCRYPTION='N';强制重建
磁盘恢复后,立即补全备份链
空间释放、MySQL 回归正常后,立刻做两件事:
- 触发一次
FLUSH LOGS;,让 binlog 切新文件,避免后续日志继续膨胀 - 执行完整逻辑备份:
mysqldump --single-transaction --routines --triggers -A > full_backup_$(date +%F).sql - 如果业务允许停机,顺手做一次物理冷备(打包
datadir),比逻辑备份更快恢复
注意:--single-transaction 依赖 MVCC,对 MyISAM 表无效;若库中混用引擎,得加 --lock-all-tables,但会锁写。
最易被忽略的一点:磁盘爆满后即使恢复了,ibtmp1 不会自动缩回原大小,它会保持膨胀后的体积直到重启或执行重建命令——下次同样操作可能更快再次填满。


















