临时表空间不足本质是GROUP BY/ORDER BY或分表关联结果集过大触发MEMORY引擎容量上限;需同步调大tmp_table_size与max_heap_table_size,且优先优化SQL和索引——如拆分UNION、确保JOIN字段有索引、避免隐式类型转换。

这是临时表空间不足的典型表现,不是内存泄漏或配置错误,本质是 GROUP BY、ORDER BY 或关联结果集过大触发了 MySQL 内部 MEMORY 引擎临时表的容量上限(默认 16MB)。
为什么分表关联查询特别容易触发这个错误
跨分表(如 t_order_202401、t_order_202402)做 JOIN 或 UNION ALL 后再聚合时,MySQL 往往无法利用索引下推,被迫将中间结果全量写入临时表;若分表数量多、单表数据量大,或关联字段无有效索引,临时表体积极易突破 tmp_table_size 和 max_heap_table_size 的较小者。
- 两个参数必须同时调高才生效,只改一个无效
- 即使调到 256MB,仍可能因排序/分组字段未走索引而退化为磁盘临时表(这时报错会变成
disk table is full) - 分表场景下,
EXPLAIN显示的type=ALL或Extra: Using temporary; Using filesort是危险信号
快速定位哪部分触发了临时表膨胀
在出错 SQL 前加 EXPLAIN FORMAT=TREE(MySQL 8.0+)或 EXPLAIN(5.7),重点看:
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
- 各
table行的rows是否远超预期(比如预估 10 万行,实际关联后生成 500 万行中间结果) - 是否出现
Using join buffer (Block Nested Loop)—— 这说明驱动表太小、被驱动表没走索引,大量数据被缓存进 join buffer,极易撑爆内存 - 聚合操作(
GROUP BY字段)是否落在分表的非分区键上(例如按user_id分表,却对create_time聚合)
不改配置的实操修复路径
优先从 SQL 和索引入手,比调大内存更治本:
- 把
UNION ALL拆成多次独立查询,在应用层合并,避免 MySQL 在服务端构造巨型临时结果集 - 确保
JOIN条件字段在所有分表上都有相同结构的索引(例如ON t1.order_id = t2.order_id,则t_order_202401和t_order_202402都要有INDEX idx_order_id (order_id)) - 用
STRAIGHT_JOIN强制驱动表顺序,让小表驱动大表,减少 join buffer 压力 - 如果只是查分页列表,用
LIMIT+WHERE下推(例如先查出满足条件的id列表,再用IN关联详情)
需要调参时的关键注意事项
仅当确认 SQL 已优化、且业务确实需要一次性拉取大量聚合结果时才调整:
- 在会话级设置更安全:
SET SESSION tmp_table_size = 268435456;(256MB),避免影响全局连接 -
max_heap_table_size必须同步设为相等值,否则以较小者为准 - 重启后失效,不要写死在
my.cnf里长期启用——它会影响所有连接的内存占用 - 注意:超过
tmp_table_size后 MySQL 会自动转用 MyISAM 磁盘临时表,此时性能断崖下跌,但不再报 “Memory table is full”
真正棘手的是那些隐式类型转换导致索引失效的关联(比如 varchar 字段和 int 变量比较),会让执行计划彻底失控——这种问题不会直接报错,但会让临时表大小难以预测。

















