应监控Created_tmp_disk_tables与Created_tmp_tables比值,超10%说明大量查询被迫落盘;配合SHOW PROCESSLIST查Copying to tmp table on disk状态、EXPLAIN分析Using temporary等高风险信号,并确认@@tmpdir实际路径及磁盘占用。

查状态变量比值最直接
MySQL 不会主动告诉你“这次查询落盘了”,但会统计全局行为。关键看 Created_tmp_disk_tables 和 Created_tmp_tables 的比值:
- 执行
SHOW GLOBAL STATUS LIKE 'Created_tmp%';,拿到两个数值 - 如果
Created_tmp_disk_tables / Created_tmp_tables > 0.1(即超 10%),说明大量查询被迫写磁盘临时表 - 这个比值比单看
Created_tmp_disk_tables绝对值更有意义——它排除了低频小查询的干扰
注意:该指标是累积值,需在业务低峰期采样对比,或配合监控系统观察突增趋势。
看 SHOW PROCESSLIST 状态字段
当查询正在执行且卡住时,State 列出现以下任一值,基本可断定已触发磁盘临时表:
-
Creating tmp table:刚建内存临时表,还没溢出 -
Copying to tmp table on disk:已明确落盘,正在把数据从内存拷到磁盘 -
Sorting result或Using filesort配合大偏移LIMIT,也常是落盘后继状态
这个方法实时性强,但只能看到“当前正在发生”,无法回溯历史慢查。
用 EXPLAIN + 执行计划交叉验证
EXPLAIN 本身不显示是否落盘,但它能暴露高风险信号:
- 出现
Using temporary且Extra列没有索引提示(如Using index for group-by) -
type是ALL或index,同时rows显示扫描行数远大于filtered估算返回行 -
key为空,但GROUP BY或ORDER BY字段本应能走索引
这类执行计划往往意味着中间结果太大、没索引加速,内存很快耗尽——哪怕参数调得再大,只要 SQL 写法踩坑,照样落盘。
确认落盘路径和实际空间占用
别只盯着错误日志里的 The table is full 就改参数。先定位真实落盘位置:
- 执行
SELECT @@tmpdir;查 MySQL 实际用的临时目录(常见为/tmp、/var/tmp或 RDS 自定义路径) - 运行
df -h /path/from/@@tmpdir,看对应挂载点是否真满了 - 如果是 RDS 或云数据库,还要查专属参数:
SHOW VARIABLES LIKE 'loose_rds_max_tmp_disk_space';(阿里云)、或检查ibtmp1大小(MySQL 8.0.16+ 默认走这里) - 用
lsof +D /path/to/tmpdir看是否有其他进程(如备份脚本)也在狂写同一目录
很多“磁盘满”问题其实不是 MySQL 导致的,而是路径被共用、权限不对、或 ibtmp1 涨到上百 GB 后无法收缩——这些都得靠路径确认才能绕开误判。


















