重建TEMP表空间是唯一可靠解法,因Oracle不自动回收已分配临时段;需新建temp2、切换默认、确认无会话使用旧TEMP、再drop tablespace including contents and datafiles。
global temporary table 本身不占用永久表空间,但其数据写入依赖当前会话的临时表空间;所谓“清理不了”,实际是临时段未释放,根源不在表定义,而在会话或lob操作残留。
查不到活跃会话却TEMP用满?先确认是不是TEMPORARY LOB_DATA
很多 DBA 以为 v$sort_usage 为空就代表没人在用 TEMP,但 TEMPORARY LOB_DATA 不出现在那里:
- 它由 C/Java 等长连接程序读取含 CLOB/BLOB 字段的表 + ORDER BY 或 GROUP BY 触发
- 占用后不会随语句结束自动释放,直到会话断开或显式调用 DBMS_LOB.FREETEMPORARY
- 查询方式:
SELECT sid, sql_id, contents FROM v$sort_usage WHERE contents = 'TEMPORARY LOB_DATA';
- 再关联
v$session 查来源:SELECT sid, username, program, machine FROM v$session WHERE sid IN (123,456);
TRUNCATE 或 DROP GLOBAL TEMPORARY TABLE 没用
这是常见误区:
- TRUNCATE TABLE xxx 对事务级(ON COMMIT DELETE ROWS)表无效,因为数据本就不跨事务
- 对会话级(ON COMMIT PRESERVE ROWS)表,TRUNCATE 只清当前会话数据,且需在该会话内执行
- DROP TABLE 删除的是表结构定义,不释放已分配的临时段,也不影响其他会话正在使用的临时空间
- 所有这些操作都不动 TEMP 表空间里的物理 extent,更不解决高位 extent 占用问题
真正有效的清理路径只有重建TEMP表空间
Oracle 19c 的 tempfile 扩展后不回收高位 extent,SHRINK SPACE 对 TEMP 无效,RESIZE 很可能报 ORA-03297 —— 唯一可靠动作就是重建:
- 新建中转 TEMP:
CREATE TEMPORARY TABLESPACE temp2 TEMPFILE '/u01/oradata/ORCL/temp02.dbf' SIZE 2G AUTOEXTEND ON NEXT 100M MAXSIZE 16G;
- 切换默认:
ALTER DATABASE DEFAULT TEMPORARY TABLESPACE temp2;
- 验证旧 TEMP 已无使用:
SELECT sid, serial#, username FROM v$session WHERE tempseg_used > 0 AND tablespace = 'TEMP';(结果必须为空)
- 删除旧 TEMP:
DROP TABLESPACE temp INCLUDING CONTENTS AND DATAFILES;
- 注意:不能只
DROP TEMPFILE,那只会让表空间变 EMPTY,下次排序直接报 ORA-01652
重建后仍反复涨满?盯住应用层的CLOB长连接
临时表空间重建只是清零,不是根治:
- 如果应用(尤其是 C 程序)持续用同一连接反复查询含 CLOB 的表并排序,每次都会新占 TEMPORARY LOB_DATA
- 这类连接往往不主动断开,也不调用 DBMS_LOB.FREETEMPORARY
- 解法不是 DBA 能单方面解决的:
- 要求应用改短连接,或每次查询后显式释放:
DBMS_LOB.FREETEMPORARY(l_clob_var) - 避免在 SQL 中直接
SELECT *含 LOB 字段,改用子查询或分页绕过 - 对关键报表类 SQL,加物化视图或预计算字段,减少运行时 LOB 排序
否则,哪怕你每周重建一次 TEMP,三个月后还是 100%


















