mysql临时表生命周期仅限于当前会话,而非存储过程或事务;会话结束时自动销毁,但连接复用时需显式drop以避免命名冲突和资源占用。

临时表生命周期只到会话结束,不是存储过程结束
MySQL 的 CREATE TEMPORARY TABLE 创建的临时表,作用域绑定在**连接(session)**,而非存储过程或事务。哪怕你在存储过程中创建、使用、再 DROP TEMPORARY TABLE,只要连接没断,这个临时表名就不可复用;而如果你没显式 DROP,它也会一直留到连接关闭——不是“没释放”,而是“设计上就不该这时释放”。
常见错误现象是:调用完一个含临时表的存储过程后,再立刻用相同名字建新临时表,报错 ERROR 1050 (42S01): Table 'xxx' already exists。这不是内存泄漏,是 MySQL 在会话级严格维护临时表命名空间。
- 临时表数据和结构都只对当前连接可见,其他会话看不见,也不写入磁盘元数据
-
DROP TEMPORARY TABLE是安全的显式清理方式,但不是必须的;连接断开时自动销毁 - 如果存储过程里用了
CREATE TEMPORARY TABLE ... SELECT,且 SELECT 很大,那临时表占用的内存(受tmp_table_size和max_heap_table_size控制)会在查询执行期间分配,但不会因为过程返回就立即归还——缓冲区释放时机取决于后续是否还有排序/JOIN 操作,而非语句块结束
为什么 SHOW PROCESSLIST 看不到临时表但内存还在涨?
临时表本身不显示在 SHOW PROCESSLIST,但它的资源消耗体现在全局状态变量里:Created_tmp_tables 和 Created_tmp_disk_tables 每次递增,说明有新临时表生成;而 Bytes_received 或 Sort_merge_passes 同步升高,往往意味着排序缓冲(sort_buffer_size)被长期持有。
尤其当存储过程内嵌循环、多次执行带 ORDER BY 的子查询时,每次迭代都可能触发新的内存临时表分配,但 MySQL 不会为每次迭代单独回收——它等整个会话空闲或缓冲区被复用时才尝试归还。
- 检查是否启用了
SQL_BUFFER_RESULT:加了这个提示会让 MySQL 强制把结果物化进临时表,反而延迟内存释放 - 避免在循环体内反复
CREATE TEMPORARY TABLE+INSERT ... SELECT:改用单次建表 +INSERT ... ON DUPLICATE KEY UPDATE或分批处理 - 确认
tmp_table_size和max_heap_table_size相等且合理(如 64M),否则哪怕内存充足,也会因参数不一致强制落盘,导致磁盘临时表残留和内存卡住
PHP/Java 调用存储过程后临时表“赖着不走”的真实原因
不是 MySQL 不放,是客户端没关连接。phpEnv、PDO、JDBC 连接池默认复用连接,一次调用存储过程后连接保持 Sleep 状态,临时表名和分配的内存缓冲(sort_buffer_size、join_buffer_size)全挂在那儿。你看到的“内存不释放”,90% 是连接池长连接+未设 wait_timeout 导致的。
- PHP 中用
PDO::ATTR_PERSISTENT => false关闭持久连接,或调用完显式$pdo = null - Java 侧检查连接池配置,确保
maxLifetime和idleTimeout小于 MySQL 的wait_timeout(建议设为 60 秒) - 在存储过程末尾加
DROP TEMPORARY TABLE IF EXISTS tmp_xxx;,虽非必需,但能减少命名冲突和调试干扰 - 别依赖
mysqli_free_result()清临时表——它只释放结果集指针,不影响已建的临时表
临时表落盘后磁盘文件不删,等于内存也“卡住”
当临时表超出 tmp_table_size,MySQL 会把它写到 tmpdir(通常是 /tmp 或 C:\Windows\Temp)。这些磁盘临时表文件(形如 #sql_XXXX_YY.MYD)本该在会话断开时自动清理,但如果 tmpdir 所在分区满了、权限不对、或 mysqld 进程被 kill -9 中断,文件就会残留——此时 SHOW GLOBAL STATUS LIKE 'Created_tmp_disk_tables' 持续上涨,而 df -h 显示磁盘快满,内存回收也被拖慢。
- 先查
SHOW VARIABLES LIKE 'tmpdir';,确认路径可写且空间充足 - Linux 下可手动清理:
rm -f /tmp/#sql_*(需停服务或确保无活跃会话) - Windows phpEnv 用户注意:
tmpdir默认可能是C:\Windows\Temp,权限受限,建议在my.ini中显式改成C:/phpEnv/MySQL/tmp并授予权限 - 临时表落盘后,即使连接断了,MySQL 也不会主动删磁盘文件——这是内核行为,靠的是下次启动时的初始化清理逻辑,不是实时机制
Created_tmp_disk_tables 每分钟涨几百,优先看连接池配置和 tmpdir 健康度,而不是怀疑 MySQL 有 bug。











