MySQL 8.0 默认临时表引擎为TempTable,不支持TEXT/BLOB、DISTINCT与GROUP BY混用等旧语法,需通过SET SESSION/GLOBAL或配置文件临时切回MEMORY引擎过渡,但根本解法是重构SQL。

MySQL 8.0 默认启用 TempTable 引擎,但老 SQL 会崩
MySQL 8.0 把临时表默认引擎从 MEMORY 换成了 TempTable,后者支持 BLOB/TEXT、更准的排序和压缩,但有个硬伤:它不支持某些 5.7 里习以为常的语法,比如 CREATE TEMPORARY TABLE ... SELECT ... GROUP BY 中带 DISTINCT 或窗口函数的组合,直接报错 ERROR 1815 (HY000): Internal error: Cannot create temporary table with engine TempTable。
这不是配置错了,是引擎能力边界变了。别急着改 SQL——先确认是不是真被 TempTable 卡住:
- 查当前设置:
SELECT @@default_tmp_storage_engine;,8.0 默认返回TempTable - 看错误是否含
Cannot create temporary table with engine TempTable或Unsupported type for temporary table - 检查出问题的 SQL 是否用了
TEXT字段、JSON列、或GROUP BY+DISTINCT混用
临时切回 MEMORY 引擎的实操方式
最稳的过渡方案不是禁用 TempTable,而是让特定连接或全局临时切回 MEMORY,避开兼容性雷区:
- 只对当前连接生效(推荐用于调试):
SET SESSION default_tmp_storage_engine = 'MEMORY'; - 全局生效(需 SUPER 权限,重启后失效):
SET GLOBAL default_tmp_storage_engine = 'MEMORY'; - 永久生效:在
my.cnf的[mysqld]段加一行:default_tmp_storage_engine = MEMORY,然后重启 mysqld - 注意:
MEMORY不支持TEXT/BLOB,如果 SQL 真用了这些类型,切回去也会报ERROR 1163 (42000)——这时必须重构 SQL,不能硬切
为什么不能直接禁用 TempTable?
TempTable 是 MySQL 8.0 的核心组件,不是插件,无法用 UNINSTALL PLUGIN 卸载。它深度集成在查询优化器、内部排序、聚合计算中。强行绕过会导致:
- 某些内置函数(如
JSON_TABLE)执行失败 -
EXPLAIN FORMAT=TREE输出异常或缺失 - 大结果集
ORDER BY或GROUP BY性能陡降(MEMORY无磁盘溢出能力) - 升级后首次运行
mysql_upgrade可能因元数据校验失败中断
所以“切回 MEMORY”只是过渡手段,不是终点。
真正要修的其实是 SQL 和表结构
报错根源往往不在引擎本身,而在老写法撞上了新限制。优先排查这几类:
- 临时表定义里有没有
TEXT、MEDIUMTEXT、JSON字段?有就得拆成多字段或改用VARCHAR(10000)代替 - 是否在
SELECT ... GROUP BY里混用了DISTINCT和聚合函数?8.0 要求所有非聚合列必须显式出现在GROUP BY中 - ORM 自动生成的 SQL(如 Django 的
values_list().distinct())可能触发隐式临时表,需加.order_by()显式声明排序字段 - 检查慢日志里是否高频出现
Created tmp table,这类语句就是高危目标
引擎切换只是止痛药;SQL 改写才是手术刀。尤其当业务已上线,临时切 MEMORY 后务必监控 Created_tmp_disk_tables 突增——那说明内存撑不住了,得立刻处理根本问题。


















