Oracle 11g及以上版本不能用ALTER DATABASE TEMPFILE RESIZE缩小临时文件,因末尾存在未释放的已分配区(extent)会导致ORA-03297错误;必须使用ALTER TABLESPACE SHRINK SPACE或SHRINK TEMPFILE命令,且执行前需确认无活跃会话占用、权限充足,并注意SHRINK TEMPFILE才真正减小物理文件尺寸。

不能直接用 ALTER DATABASE TEMPFILE RESIZE 缩小临时文件——99% 的 ORA-03297 错误都源于此。 Oracle 11g 及以上版本必须用 SHRINK 系列命令,否则会因末尾存在未释放的已分配区(extent)而失败。
为什么 RESIZE 总是报 ORA-03297?
临时文件不会在排序结束后自动归还物理空间。v$tempfile.bytes 显示的是物理分配大小,不是真实占用;真正反映实际使用的,是 V_$TEMP_EXTENT_POOL.bytes_cached。哪怕 v$sort_usage 查不到活跃会话,文件末尾仍可能残留已分配但未归还的 extent,RESIZE 会拒绝把文件缩到该位置之前。
-
ORA-03297: file contains used data beyond requested RESIZE value不代表“还有数据在用”,而是“有已分配区落在目标尺寸之后” - 该限制与 autoextensible 设置无关,所有 11g+ 版本均存在
- 即使临时表空间设为
REUSE,也不影响 shrink 前的清理逻辑
用 SHRINK SPACE 还是 SHRINK TEMPFILE?
两者都在线执行、不锁库,但适用场景不同:
-
ALTER TABLESPACE TEMP SHRINK SPACE:自动遍历所有 tempfile,合并空闲区、释放尾部空间。适合单文件或想统一处理的场景 -
ALTER TABLESPACE TEMP SHRINK TEMPFILE '/path/to/temp01.dbf':只动指定文件。适合多文件 temp 表空间中某一个膨胀严重、其他文件尚可的情况 - 二者都支持
KEEP子句,例如KEEP 512M—— 注意这不是“保留 512M 可用空间”,而是“收缩后物理文件至少 512MB”,且该值必须 ≥ 当前真实已用空间(四舍五入到 extent 边界),否则静默无效
执行前必须确认的三件事
shrink 不会主动 kill 会话,它会等待占用释放。卡住 ≠ 命令错,大概率是没清干净:
- 查真实占用:
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 - 观察释放进度:
SELECT file_id, bytes_cached FROM V_$TEMP_EXTENT_POOL,等bytes_cached持续下降再执行 shrink - 权限检查:
SELECT * FROM session_privs WHERE privilege = 'ALTER TABLESPACE',缺权限会报ORA-01031
收缩后磁盘空间没释放?注意这个细节
shrink 成功只表示 Oracle 内部标记了空间可重用,但操作系统层面的文件大小不会自动缩小——SHRINK TEMPFILE 才会真正减小物理文件尺寸;SHRINK SPACE 只调整逻辑容量,后续新排序可能复用这些空间,但文件本身仍占磁盘。
- 要立刻回收磁盘空间,必须用
SHRINK TEMPFILE,而非SHRINK SPACE - 如果执行后
ls -lh看文件大小没变,说明你用的是SHRINK SPACE,或者SHRINK TEMPFILE被阻塞(仍有未释放 extent) - 临时文件路径含 ASM 别名时,
SHRINK TEMPFILE中的路径必须和dba_temp_files.file_name完全一致,大小写、斜杠方向都不能错


















