ALTER TABLE爆磁盘主因是tmpdir空间不足,而非datadir满;默认/tmp常为tmpfs内存挂载(仅1–2GB),而ADD INDEX、MODIFY COLUMN等操作会在tmpdir生成数GB排序文件或中间表。

ALTER TABLE 为什么爆磁盘:tmpdir 不是数据目录
执行 ALTER TABLE 报 The table '#sql-xxx' is full 或 OS error code 28: No space left on device,基本不是 datadir 满了,而是 MySQL 在 DDL 过程中把临时文件写进了 tmpdir——它默认指向 /tmp,而这个路径在多数 Linux 发行版里是 tmpfs 内存挂载,大小常只有 1~2GB,远小于物理磁盘容量。
真正写入 tmpdir 的场景包括:
-
ADD INDEX或MODIFY COLUMN触发排序阶段,生成多路归并临时文件(可能达原表 1.5 倍大小) -
ALGORITHM=COPY模式下重建表,中间表和日志缓冲区也走tmpdir -
innodb_online_alter_log_max_size不足时,DML 日志溢出写入tmpdir
注意:innodb_tmpdir 只影响 InnoDB 临时表,不影响排序类操作;tmpdir 才是 DDL 临时文件的主路径。
怎么查 tmpdir 实际空间和瓶颈点
别靠猜,分两步确认:
- 进 MySQL 查配置:
SELECT @@tmpdir, @@innodb_tmpdir;—— 若返回/tmp或空值,就按系统默认处理 - 登服务器查真实空间:
df -h /tmp看可用容量;df -i /tmp看 inode 是否耗尽(小文件极多时常见)
如果 df -h /tmp 显示类型是 tmpfs,且 “Size” 列明显偏小(比如只有 2GB),那问题就定位准了。此时改 tmpdir 比扩容 /tmp 更可靠。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
如何安全绕过 tmpdir 空间限制
核心思路是让临时文件落地到有足够空间的 SSD 分区,而不是内存挂载点:
- 启动前修改配置:在
my.cnf中设tmpdir = /data/mysql/tmp(确保该路径所在磁盘空闲 ≥ 表大小 × 2) - 运行时临时切换(仅限当前会话):
SET SESSION tmpdir = '/data/mysql/tmp';(需 MySQL 8.0.30+,且用户有 FILE 权限) - 强制走拷表路径规避排序:用
ALTER TABLE t ADD INDEX idx_x (x) ALGORITHM=COPY, LOCK=NONE;—— 此时不依赖sort_buffer_size,也不生成大规模排序临时文件
注意:ALGORITHM=COPY 虽不排序,但仍需双倍磁盘空间(原表 + 中间表),所以仍要确保 tmpdir 所在分区够大。
容易被忽略的隐性空间消耗
除了 tmpdir,还有三处空间压力常被漏掉:
-
binlog爆涨:单次ALTER可能生成数 GB binlog,若max_binlog_size设得小,会频繁轮转,甚至因写满binlog目录导致所有写入阻塞 -
redo log和undo log压力:大表重建期间日志写入激增,可能触发innodb_log_file_size不足告警 -
DATA_FREE不释放:即使 DDL 成功,旧表碎片空间(DATA_FREE)也不会自动归还操作系统,必须靠ALTER TABLE ... ENGINE=InnoDB或OPTIMIZE TABLE主动整理
最危险的是把 tmpdir、binlog、datadir 全部放在同一块盘上——DDL 一跑,三者同时争抢空间,失败概率极高。










