建索引会用到临时表空间,因为需对数据排序并构建B-Tree结构:排序阶段内存不足时在ibtmp1做外部归并排序;COPY算法需重建表并逐批插入;INPLACE模式仍需临时表记录DML变更及处理TEXT/BLOB等大字段。

因为建索引过程本身会大量生成内部临时表,尤其是当使用 ALGORITHM=COPY 或旧版本 InnoDB 时,MySQL 需要重建整张表并排序数据——这一步几乎必然触发磁盘临时表,直接往 ibtmp1 里猛写。
建索引为什么会用到临时表空间?
MySQL 添加索引不是“贴个标签”就完事。它得把所有行按索引字段重新排序、构造 B-Tree 结构。这个过程需要中间暂存区:
- 排序阶段:若内存不够(
innodb_sort_buffer_size太小),就会在ibtmp1里做外部归并排序 - 重建表阶段(
COPY算法):先建新表结构 + 索引,再逐行读原表、排序插入——每一批插入都可能产生临时排序缓冲和中间结果 - Online DDL 的
INPLACE模式虽不重建表,但依然要用临时表记录 DML 变更(log buffer+sort buffer+ 内部临时表),尤其在大并发写入时
ALGORITHM=INPLACE 就不会爆 ibtmp1 吗?
不一定。即使用了 ALGORITHM=INPLACE, LOCK=NONE,以下情况仍会高频落盘:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 表里有
TEXT/BLOB字段:这类列无法全放内存临时表,强制走磁盘临时表 -
max_heap_table_size和internal_tmp_mem_storage_engine(MySQL 8.0)设得太低:排序中间结果一超限就刷进ibtmp1 - 并发 DML 太多:DDL 过程中积累的变更日志(
online log)本身也占临时空间,且无法被及时合并 - MySQL 5.7 及更早版本:
INPLACE对二级索引创建仍可能用到 MyISAM 引擎的磁盘临时表(路径由tmpdir控制)
怎么快速判断是不是建索引导致的 ibtmp1 暴涨?
别等它涨到上百 GB 再反应。建索引前、中、后盯住三个指标:
- 执行
SHOW GLOBAL STATUS LIKE 'Created_tmp_disk_tables':如果这个值在建索引期间突增数百/数千,基本就是它干的 - 查
SELECT @@innodb_temp_data_file_path确认当前ibtmp1路径;用ls -lh /var/lib/mysql/ibtmp1实时看文件体积变化 - 观察
SHOW PROCESSLIST中该 DDL 线程状态:若长期卡在altering table或copy to tmp table,说明正在重度依赖临时空间
真正难处理的不是“要不要调参”,而是建索引时临时表空间的消耗不可预测——它取决于实时数据分布、并发负载、甚至 buffer pool 当前碎片程度。所以生产环境加索引,永远优先考虑分批导出+索引预建,而不是赌 INPLACE 一定稳。

















