某生产环境执行表引擎转换操作时突发报错:
ALTER TABLE student ENGINE=InnoDB;
ERROR 1114 (HY000): The table 'student' is full
初步排查发现,数据库临时目录/tmp仅剩不足 100MB 空间,而数据目录磁盘使用率已达 95%。通过调整临时目录路径至大空间分区后,操作成功执行。这一现象揭示了 Online DDL 操作中隐藏的空间需求复杂性。
- 作用机制:在添加索引、修改表结构等操作中,InnoDB 通过临时日志(
ibtmp文件)记录并发的 DML 操作,确保在线操作的一致性。
- 关键参数:
innodb_online_alter_log_max_size(默认 128MB)控制单个日志文件大小,若并发修改频繁且 DDL 耗时较长,可能触发DB_ONLINE_LOG_TOO_BIG错误。
- 风险场景:
- 产生场景:当 DDL 操作需要重建表(如修改引擎、添加非索引列)时,MySQL 会在临时目录(
tmpdir)生成排序文件,用于临时存储数据。
- 路径陷阱:
- 默认路径为
/tmp,若该目录空间不足(如系统默认的 tmpfs 仅 1GB),会导致Temporary file write failure错误。
- 案例:将
tmpdir设置为 1MB 后,执行ALTER TABLE student ADD INDEX(name)直接报错。
- 生成逻辑:Online DDL 过程中会在数据目录创建以
#sql-ib开头的临时中间表,大小可能与原表相当。
- 空间计算:假设原表占用 500GB,执行
ALTER TABLE ... ENGINE=InnoDB时,数据目录需额外 500GB 空间用于中间表。
- 数据目录限制:通过磁盘镜像创建 600MB 受限目录:
dd if=/dev/zero of=/root/test.img bs=60M count=10
losetup /dev/loop0 /root/test.img
mount -t ext3 /dev/loop0 /opt/mysql/data/3310/my_test
- 临时目录限制:将
/tmp大小限制为 1MB:
mount -o remount,size=1M tmpfs /tmp
解决:扩大临时目录至 500MB 后成功:
mount -o remount,size=500M tmpfs /tmp
解决:清理数据目录至使用率 < 30% 后执行成功。
所需空间 = 原表大小 + 临时日志最大体积 + 临时排序文件大小
- 临时日志体积 = 并发 DML 速率 × DDL 耗时 × 单条日志大小
- 临时排序文件 ≈ 原表索引大小(添加索引场景)
| 参数名称 | 作用描述 | 推荐配置 |
innodb_online_alter_log_max_size |
限制临时日志单个文件大小,避免耗尽磁盘空间 |
生产环境建议 512MB~2GB,根据并发写入量调整 |
tmpdir |
临时文件存储路径,建议设置为独立大空间分区(如 /data/tmp) |
SET GLOBAL tmpdir='/data/tmp';(需重启生效) |
sort_buffer_size |
排序操作缓冲区大小,调大可减少磁盘临时文件生成 |
默认为 256KB,复杂排序场景建议 1MB~8MB |
-
事前规划
- 通过
pt-duplicate-key-checker提前分析索引必要性,减少无效 DDL。
- 使用
SHOW TABLE STATUS预估表大小,结合公式计算所需空间。
-
事中监控
- 实时监控
/tmp和数据目录磁盘使用率:
watch -n 5 'df -h /tmp /data/mysql'
- 跟踪临时文件生成:
SELECT * FROM INFORMATION_SCHEMA.FILES WHERE FILE_NAME LIKE '%ibtmp%';
-
事后清理
- 定期清理历史临时文件:
find /data/tmp -name '#sql-ib*.tmp' -mtime +1 -delete
- 对大表使用
pt-osc或gh-ost工具,减少对临时空间的依赖。
Online DDL 的空间问题本质是 **"数据流动的中间态管理"**—— 临时日志承载着并发修改的一致性,临时文件记录着结构变更的中间结果,中间表则是数据重构的载体。理解这三重空间需求,提前规划存储资源,才能避免 "小空间引发大故障" 的悲剧。记住:在数据库操作中,每一次数据的 "变形" 都需要足够的 "舞台" 来完成。