必须将tmp_table_size与max_heap_table_size设为相同值,因内存临时表大小取二者较小值;若不一致(如前者64M、后者16M),实际仅用16MB,导致Created_tmp_disk_tables持续增长。
MySQL 的 tmp_table_size 和 max_heap_table_size 才是控制内存临时表大小的关键参数,Variables 本身只是查看入口,不能“动态调整”——改的是变量值,不是变量名。
tmp_table_size 临时表还是用磁盘?MySQL 要求两个参数必须同时满足:内存临时表大小不能超过 tmp_table_size,也不能超过 max_heap_table_size。实际生效的是二者中的较小值。
tmp_table_size = 64M,但 max_heap_table_size = 16M,那最多只用 16MB 内存SHOW VARIABLES LIKE '%table_size%'; 确认两者当前值SHOW STATUS LIKE 'Created_tmp_disk_tables'; 是否持续增长它们都支持 SET SESSION 和 SET GLOBAL,但作用范围和持久性差异极大:
SET SESSION tmp_table_size = 67108864; —— 仅对当前连接生效,适合调试单条大查询SET GLOBAL tmp_table_size = 67108864; —— 影响后续新连接,**不改变已有连接的会话值**my.cnf 的 [mysqld] 段64M 要写成 67108864,或用 64 * 1024 * 1024 计算后赋值EXPLAIN 的 Using temporary 带偏这个提示只表示“逻辑上需要临时结构”,不等于一定建了内存/磁盘临时表。是否落地取决于数据量和两个 size 参数的实际交集:
GROUP BY + ORDER BY 字段不一致时大概率触发DISTINCT 配合多列、无合适索引时容易触发UNION 或聚合,且结果集超限SELECT @@tmp_table_size, @@max_heap_table_size; + SHOW STATUS LIKE 'Created_tmp%'; 对比前后变化真正要注意的是:调大这两个值会直接占用每个连接的内存上限,连接数高时可能引发 OOM;而调太小又会让本可内存完成的排序分组被迫写磁盘。平衡点得看实际慢查的 Created_tmp_tables 和 Created_tmp_disk_tables 比值,而不是盲目堆内存。