alter tablespace temp shrink space是最准最安全解法,因11g≥11.1.0支持原生收缩,可释放已分配未回收的临时段;v$sort_usage为空但dba_temp_free_space显示100%属“假满”,系高位extent未释放所致,需先杀长期会话再执行shrink。

Oracle 11g 临时段“占满磁盘但查不到活跃会话”,不是真满了,而是已分配未回收——ALTER TABLESPACE temp SHRINK SPACE 是最准、最安全的解法,前提是版本 ≥ 11.1.0 且无长期占用会话。
为什么 v$sort_usage 为空但 dba_temp_free_space 显示 100%?
临时文件(tempfile)一旦扩展,Oracle 就不会自动收缩其物理大小,即使所有排序早已结束。SMON 进程本该清理残留临时段,但在高并发或异常中断后可能卡住或延迟。此时 v$temp_extent_pool.bytes_cached 仍维持高位,dba_temp_free_space.free_space 接近 0,但 v$sort_usage 查不到任何会话 —— 这是典型的“假满”状态,磁盘空间被已分配但空闲的 extent 占着不动。
注意:dba_free_space 对临时表空间完全无效,它只反映永久表空间;必须用 dba_temp_free_space 或 v$temp_extent_pool 看真实空闲量。
ALTER DATABASE TEMPFILE ... RESIZE 为什么总报 ORA-03297?
因为 RESIZE 要求文件末尾没有已分配的 extent,而临时文件高位常驻着未释放的排序段。强行 RESIZE 必然失败,这不是权限或语法问题,是 Oracle 的底层设计限制。
- 别试
ALTER DATABASE TEMPFILE '/path/to/temp01.dbf' RESIZE 512M,大概率报错 -
SHRINK TEMPFILE或SHRINK SPACE才是正解:它们会先移动并释放高位 extent,再收缩文件 - 若执行后
bytes_cached不下降,说明仍有会话在写该文件,得等或杀会话
什么情况下 SHRINK SPACE 会失效?
SHRINK SPACE 不杀会话,只等空闲段释放。如果存在长期运行的大排序(比如 ETL 导出、报表聚合),或者应用用了 WITH 子句建临时结果集却没显式提交/断开连接,SHRINK 就会卡住不动,甚至只收缩部分文件。
- 先查真实占用者:
SELECT s.sid, s.serial#, s.username, u.blocks * t.block_size / 1024 / 1024 mb_used FROM v$sort_usage u, v$session s, v$transaction t WHERE u.session_addr = s.saddr AND u.xidusn = t.xidusn(+) ORDER BY mb_used DESC - 对长时间不动、MB 很大的会话,用
ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE - 执行前建议等 5–10 分钟,观察
v$temp_extent_pool.bytes_cached是否持续下降 - 若仍无效,可尝试诊断事件:
ALTER SESSION SET EVENTS 'immediate trace name DROP_SEGMENTS level 4'(其中 4 是 TEMP 表空间的ts# + 1)
重建 TEMP 表空间是不是更彻底?
是,但代价明确:需新建表空间、切换默认、确认无会话残留、再 DROP TABLESPACE ... INCLUDING CONTENTS AND DATAFILES。整个过程不需停库,但要求业务 SQL 暂时避开大规模排序操作——否则新 TEMP 尚未就绪时就会触发 ORA-01652。
真正释放磁盘空间,必须删掉 tempfile 物理文件;仅 DROP TEMPFILE 只删控制文件记录,不删磁盘文件,且会让表空间进入不可用状态。所以重建虽稳妥,但属于兜底动作,日常优先用 SHRINK SPACE。
最易被忽略的一点:SHRINK TEMPFILE 加 KEEP 子句(如 KEEP 512M)不是可有可无的防护——它防止缩过头,避免后续一个大 ORDER BY 直接因无空间而失败。











