MySQL 8.0+ 默认用 TempTable 引擎更靠谱,因其支持 TEXT/BLOB、动态行格式节省30%~50%内存、内存池管理防OOM、高并发锁优化,而 MEMORY 引擎不支持大字段、固定长度浪费内存、超限即报错且不自动落盘。

MySQL 8.0+ 默认用 TempTable 引擎处理内存临时表,比老版本的 MEMORY 更稳、更省、更支持变长字段;盲目调大 tmp_table_size 反而容易引发并发内存超限,治标不治本。
为什么 internal_tmp_mem_storage_engine 设成 TempTable 更靠谱
MySQL 5.7 及以前默认用 MEMORY 引擎建内存临时表,但它有硬伤:不支持 TEXT/BLOB、行格式固定、无压缩、超限就直接落地磁盘。MySQL 8.0 引入 TempTable 引擎后,这些问题基本被解决:
-
TempTable支持动态行格式,能紧凑存储 VARCHAR 和 NULL 值,同样数据量比MEMORY少占 30%~50% 内存 - 它原生支持
TEXT和BLOB字段(以 off-page 方式管理),避免“一选 TEXT 就强制落盘”的尴尬 - 内部做了内存池管理和轻量级锁优化,高并发下比
MEMORY更少争抢、更少 OOM 风险 - 只要没超
tmp_table_size,它就纯内存运行;超了才转磁盘(默认用 InnoDB 临时表)
确认当前设置:SELECT @@internal_tmp_mem_storage_engine;
如果不是 TempTable,请在配置文件中加:
internal_tmp_mem_storage_engine = TempTable
tmp_table_size 和 max_heap_table_size 必须一致,且不能只看单条查询
这两个参数取较小值作为单个临时表的内存上限。设成不一致(比如一个 256M、一个 64M),等于白调——MySQL 按 64M 切。
- 别按服务器总内存算,要按「并发连接数 × 单次最大临时表预期」来反推。64G 内存服务器,200 并发下设
tmp_table_size = 1G,理论峰值就是 200G,必爆 - 建议从
64M或128M起步,上线后盯SHOW STATUS LIKE 'Created_tmp_disk_tables';增速。如果每秒增长 > 1,再逐步上调 - 注意:这个值是 per-session 的,不是全局总和。每个会话都可能独占一份
GROUP BY / ORDER BY 场景下,加索引比调参更有效
临时表撑爆最常发生在 GROUP BY 和 ORDER BY,尤其当字段没索引、或 SELECT 包含大字段时。这时候光调 tmp_table_size 是掩耳盗铃:
- 如果
GROUP BY a, b没覆盖索引,MySQL 不得不把全量行读进来建临时表分组;加联合索引INDEX(a,b)后,可能直接用索引扫描+流式分组,根本不用临时表 -
ORDER BY x LIMIT 10如果x无索引,大概率触发Using filesort+Using temporary;加索引后,排序可下推到存储层,跳过临时表 - 哪怕只加
WHERE条件也有效:比如SELECT * FROM orders GROUP BY user_id很慢,但SELECT * FROM orders WHERE created_at > '2025-01-01' GROUP BY user_id可能快十倍——因为参与分组的数据量少了
怎么确认你的查询真正在用内存临时表
别信感觉,看两个硬指标:
-
EXPLAIN输出里出现Using temporary,只代表“需要中间结构”,不等于“用了内存表”。它可能是内存,也可能是磁盘 - 查会话级状态:
SHOW SESSION STATUS LIKE 'Created_tmp%';关注Created_tmp_tables(总临时表数)和Created_tmp_disk_tables(磁盘临时表数)。如果后者 ÷ 前者 > 0.2,说明内存限额或数据类型已成瓶颈 - 对高频 SQL,开
performance_schema后查:SELECT DIGEST_TEXT, SUM_CREATED_TMP_DISK_TABLES FROM performance_schema.events_statements_summary_by_digest WHERE SUM_CREATED_TMP_DISK_TABLES > 0 ORDER BY SUM_CREATED_TMP_DISK_TABLES DESC LIMIT 5;
真正难搞的是那些“看起来简单、一跑就慢”的查询——它们往往在隐式临时表上卡住,而你连 EXPLAIN 都看不出字段是否走索引,只能靠状态变量和执行耗时交叉验证。



















