MySQL无innodb_online_copy_threshold参数,空间不足主因是tmpdir、innodb_online_alter_log_max_size及datadir剩余空间不足。

MySQL Online DDL 报错空间不足,和 innodb_online_copy_threshold 无关——这个参数根本不存在。 它是常见误传,官方文档、源码、5.7–8.4 所有稳定版均无此配置项。真正影响空间的关键参数是 innodb_online_alter_log_max_size、tmpdir 和数据目录本身可用空间。
为什么搜到 innodb_online_copy_threshold 会误导人
该名称混用了两个真实概念:innodb_sort_buffer_size(排序缓冲区大小)和早期 Percona 分支中一个已废弃的内部阈值逻辑。MySQL 官方从不通过“阈值”控制是否走 copy-on-write;是否重建表由 DDL 类型、存储引擎能力、ALGORITHM 显式指定共同决定,不是靠某个 magic number 自动切换。
如果你在监控脚本、运维文档或某篇博客里看到它被当作调优项,基本可以判定:
- 作者没验证过源码或手册,直接复制了错误信息
- 把
innodb_sort_buffer_size或tmp_table_size的作用张冠李戴了 - 混淆了 MySQL 与 MariaDB/Percona 的参数命名(后者有类似语义但名字不同)
tmpdir 空间不足:最常触发 ERROR 1878 (HY000): Temporary file write failure
当执行 ADD INDEX、MODIFY COLUMN 或 ENGINE=InnoDB 这类需排序或重建的 Online DDL 时,MySQL 会在 tmpdir 下写临时排序文件(如 /tmp/#sql-xxx)。默认指向 /tmp,而很多系统用 tmpfs 挂载,仅 1–2GB,远不够处理百 GB 表。
实操建议:
- 运行
SHOW VARIABLES LIKE 'tmpdir';确认当前路径 - 检查该路径磁盘:用
df -h /tmp(或对应路径),别只看df -h / - 修改方式:在
my.cnf中设tmpdir = /data/mysql-tmp(确保该目录有足够空间且 MySQL 进程可写) - 改完必须重启 mysqld——
SET GLOBAL tmpdir不生效 - 临时应急可手动清空
/tmp下以#sql-开头的残留文件(确认无活跃 DDL 后)
innodb_online_alter_log_max_size 不够:并发 DML 多时易爆 DB_ONLINE_LOG_TOO_BIG
这个参数控制 Online DDL 期间记录并发 DML 的日志上限,默认 128MB。它不是“磁盘配额”,而是内存+临时文件联合使用的缓冲上限。一旦超过,MySQL 直接中止 DDL 并回滚未提交的 DML——不是报磁盘满,而是明确报错 DB_ONLINE_LOG_TOO_BIG。
适用场景有限,仅当同时满足以下条件才需调大:
- DDL 操作本身耗时长(如大表加索引 >30 分钟)
- 期间有持续高并发 UPDATE/INSERT/DELETE
- 原表行数极大(>1 亿)且每行变更频繁
调大建议:
- 先查当前值:
SHOW VARIABLES LIKE 'innodb_online_alter_log_max_size'; - 按需设为 268435456(256MB)或 536870912(512MB),单位是字节
- 注意:增大后不会自动释放内存,只是放宽上限;过大反而可能拖慢日志刷盘
- 更治本的做法是错峰执行 DDL,避开业务高峰
中间表占用数据目录:最容易被忽略的“隐形空间杀手”
Online DDL 中凡涉及重建表的操作(如 ENGINE=InnoDB、ADD COLUMN ... NOT NULL),都会在 datadir 下生成以 #sql-ib 开头的中间表文件,大小≈原表 .ibd。这意味着:原表占 800GB,操作期间至少需要额外 800GB 可用空间。
这里没有参数能“省空间”,只有硬性检查和预估:
- 查数据目录剩余空间:
df -h $(mysql -Nse "SELECT @@datadir") - 查目标表大小:
SELECT round((data_length + index_length) / 1024 / 1024 / 1024, 2) AS gb FROM information_schema.tables WHERE table_schema='db' AND table_name='t'; - 若剩余空间
- 不要依赖
data_free字段——那是碎片空间,中间表不复用它
真正容易被忽略的是:即使你调大了所有参数、换掉了 tmpdir,只要 datadir 分区剩不下一张表的空间,DDL 就会卡在最后一步,报 ERROR 1114 (HY000): The table 'xxx' is full——这时查 df 才发现根分区只剩 2GB。


















