重建temp表空间是最直接有效的解法,因其不自动回收已分配临时段;需新建temp2、切换默认、确认无会话使用旧temp、再drop tablespace including contents and datafiles。
临时表空间长期显示 100% 使用率,但查不到活跃排序会话?这不是 bug,是 oracle 的设计行为——它不自动回收已分配的临时段。重建 temp 表空间是最直接有效的解法。
为什么 ALTER DATABASE TEMPFILE ... RESIZE 常失败
临时文件(tempfile)一旦扩展,高位区(high water mark)若仍有未释放的 extent,执行 RESIZE 就会报 ORA-03297。这不是磁盘满了,而是 Oracle 认为“那块地方还可能被重用”。coalesce 对临时表空间无效;shrink space 语法根本不支持临时表空间。
- 检查真实空闲空间必须用
v$temp_space_header,不是dba_free_space - 验证语句:
SELECT tablespace_name, round((free_blocks*block_size)/1024/1024) free_mb FROM v$temp_space_header; - 如果
free_mb明显大于 0,说明空间实际可用,只是监控视图(如dba_temp_free_space)统计口径不同
重建 TEMP 表空间的安全操作顺序
全程可在数据库 OPEN 状态下完成,无需停机,但必须避开大规模排序或建索引窗口,否则新 TEMP 未就绪时会触发 ORA-01652。
- 新建临时表空间:
CREATE TEMPORARY TABLESPACE temp2 TEMPFILE '/u01/oradata/ORCL/temp02.dbf' SIZE 1024M AUTOEXTEND ON NEXT 100M MAXSIZE 8G; - 切换默认:
ALTER DATABASE DEFAULT TEMPORARY TABLESPACE temp2; - 确认旧
TEMP已无使用:SELECT sid, serial#, username, program FROM v$session WHERE tempseg_used > 0 AND tablespace = 'TEMP';—— 结果必须为空 - 删除旧表空间:
DROP TABLESPACE temp INCLUDING CONTENTS AND DATAFILES;(缺INCLUDING CONTENTS会残留临时段)
PL/SQL 中排序操作如何避免压垮 TEMP
排序不是写 SQL 才发生——GROUP BY、ORDER BY、UNION、建索引、甚至某些子查询都会触发磁盘排序。关键在控制 PGA 分配和减少物理排序次数。
- 优先加索引:比如
ORDER BY create_date DESC,就在create_date上建INDEX_DESC,让 Oracle 直接走索引扫描,跳过排序 - 查高开销 SQL:
SELECT * FROM V$SQL_WORKAREA WHERE policy = 'AUTO' AND last_execution = 'MULTIPASS',这类是真正吃 TEMP 的大户 - 临时调大单会话 PGA:
ALTER SESSION SET WORKAREA_SIZE_POLICY = MANUAL; ALTER SESSION SET SORT_AREA_SIZE = 209715200;(慎用,仅调试) - 避免在 PL/SQL 循环里反复
ORDER BY小结果集——合并后一次排序更省
重建 TEMP 的本质,是放弃对“已分配但空闲”空间的徒劳回收,转而用干净的新 tempfile 替代。真正容易被忽略的点是:删掉旧 TEMP 后,必须手动清理操作系统层面的 temp01.dbf 物理文件——DROP TABLESPACE ... AND DATAFILES 虽然写了 DATAFILES,但在某些 ASM 或权限受限环境仍可能只删控制文件记录,不删磁盘文件。











