不能直接用alter database tempfile...resize缩容,需先确认临时表空间为本地管理且无活跃排序;再通过v$tempseg_usage验证无使用中临时段;计算真实已用空间并向上取整至extent边界设keep值;优先对单个tempfile执行shrink tempfile;若反复涨回则重建temp表空间。

不能直接用 ALTER DATABASE TEMPFILE ... RESIZE 强行缩容,大概率报 ORA-03297;SHRINK SPACE 看似简单,但跳过前提检查会静默失败或卡住。
确认临时表空间是本地管理且无活跃排序
Oracle 11g+ 的 SHRINK 命令只支持本地管理(LMT)的临时表空间,字典管理(DMT)不支持——但 Oracle 12c 默认就是 LMT,所以重点在运行时状态:
- 查
v$sort_usage:若返回任何行,说明有会话正在用临时段,SHRINK会被阻塞或部分失效 - 查
v$tempseg_usage(12c 新视图,比v$sort_usage更准):同样不能有结果 - 若发现活跃会话,先执行
ALTER SYSTEM KILL SESSION 'sid,serial#';注意不要 kill 后台进程(如PMON、SMON)
计算真实已用空间并设合理 KEEP 值
SHRINK 不会把文件缩到低于“当前最高已分配区(high water mark)”的位置,而 dba_temp_free_space 显示的 “used space” 是逻辑用量,不是物理高位。必须用 v$temp_space_header 查真实占用:
SELECT tablespace_name,
ROUND(SUM(used_blocks * block_size) / 1024 / 1024) "MB USED"
FROM v$tempseg_usage t, dba_temp_files d
WHERE t.tablespace_name = d.tablespace_name
GROUP BY tablespace_name;
得到结果后,向上对齐到 extent 边界(通常是 1MB 或 64KB,取决于 uniform size)。例如算出真实用了 128.3 MB,extent size 是 1MB,则 KEEP 至少设为 129M;设 128M 会导致命令静默无效。
优先 shrink tempfile 而非整个表空间
对单个临时文件执行 SHRINK TEMPFILE 比 SHRINK SPACE 更可控,失败时影响面小:
- 语法:
ALTER TABLESPACE TEMP SHRINK TEMPFILE '/u01/oradata/ORCL/temp01.dbf' KEEP 512M - 不加
KEEP会尽量缩到最小,但可能触发重分配开销;加了更安全,也便于后续监控是否真释放 - 如果一个表空间含多个 tempfile,逐个 shrink;别指望一次
SHRINK SPACE把所有文件都缩下去 - 缩完立刻查
dba_temp_files.bytes确认磁盘文件大小是否变化——v$temp_space_header只反映逻辑块使用,不等于文件尺寸
当 SHRINK 失败或反复涨回时,重建 TEMP 是唯一可靠解法
很多 DBA 卡在反复 SHRINK → 涨回 → 再 SHRINK,根源是 Oracle 不自动回收已分配的临时段。此时重建才是正解:
- 新建临时表空间:
CREATE TEMPORARY TABLESPACE temp2 TEMPFILE '/u01/oradata/ORCL/temp02.dbf' SIZE 1G AUTOEXTEND ON MAXSIZE 4G - 切换默认:
ALTER DATABASE DEFAULT TEMPORARY TABLESPACE temp2 - 确认旧 TEMP 无残留使用:
SELECT sid, serial#, username FROM v$session WHERE tempseg_used > 0 AND tablespace = 'TEMP'—— 结果必须为空 - 删除旧表空间:
DROP TABLESPACE temp INCLUDING CONTENTS AND DATAFILES(漏掉INCLUDING CONTENTS会导致临时段残留)
重建过程在线完成,但要注意:切换后若有长事务正用旧 TEMP,会报 ORA-01652;所以操作前最好避开批量导入、大表分析等高峰时段。











