v$transaction返回空但空间不释放,是因为该视图仅显示当前活跃事务,而断连未清理、分布式“in-doubt”事务等不在此列;需重点查v$session中status='active'且空闲超5分钟的会话,并结合v$tempseg_usage定位僵尸临时段。
查未提交事务时为什么 v$transaction 返回空但空间仍不释放
因为 v$transaction 只显示当前活跃的事务(即已开始、尚未提交/回滚),但某些会话可能已断开连接却未清理事务状态,或事务已进入“in-doubt”分布式状态,此时不会出现在该视图中。真正要盯的是 v$session 中 status = 'active' 且 sql_id 非空的会话,再关联 v$sql 看实际执行语句。
实操建议:
- 先运行
SELECT SID, SERIAL#, USERNAME, STATUS, SQL_ID, PREV_SQL_ID, LOGON_TIME FROM V$SESSION WHERE STATUS = 'ACTIVE' AND LAST_CALL_ET > 300,筛出空闲超5分钟的活跃会话 - 对每个可疑
SID,用SELECT SQL_TEXT FROM V$SQL WHERE SQL_ID = 'xxx'查最近执行语句,确认是否含大排序、哈希连接、GROUP BY或ORDER BY—— 这些最耗临时表空间 - 注意
PREV_SQL_ID可能比SQL_ID更关键:当前没在跑SQL,但上一条刚结束的大查询可能还在占用临时段
ALTER TABLESPACE TEMP SHRINK SPACE 执行失败的常见原因
这个命令看似简单,但 Oracle 实际执行时会检查临时文件中是否有“正在被使用的区(extent)”,哪怕只有一行排序结果还没被读走,就会报 ORA-1652 或直接跳过收缩。它不是强制清空,而是“尽最大努力压缩”。
实操建议:
- 确保没有会话正在执行
CREATE INDEX、SELECT ... ORDER BY、SELECT DISTINCT、MERGE等隐式使用临时表空间的操作 - 如果收缩失败,别反复重试,先查
V$TEMPSEG_USAGE:SELECT SESSION_ADDR, SQL_ID, SEGMENT_TYPE, BLOCKS FROM V$TEMPSEG_USAGE ORDER BY BLOCKS DESC,定位具体是哪个会话占着大块临时段 -
SHRINK SPACE不支持手动指定 tempfile 路径;如需精准控制,改用ALTER DATABASE TEMPFILE '/path/to/temp01.dbf' RESIZE 1G,但必须保证新大小 ≥ 当前已分配的最小单位(通常为区大小 × 2)
杀会话后临时段仍不释放?检查 V$SORT_USAGE 和 V$TEMPSEG_USAGE
即使 ALTER SYSTEM KILL SESSION 'sid,serial#' 返回成功,Oracle 也可能因 PMON 尚未完成清理而残留临时段。这时 V$TEMPSEG_USAGE 可能还显示该会话地址,但 V$SESSION 已消失 —— 这是典型“僵尸临时段”。
实操建议:
- 运行
SELECT * FROM V$TEMPSEG_USAGE WHERE SESSION_ADDR IN (SELECT SADDR FROM V$SESSION WHERE STATUS = 'KILLED'),确认是否真有残留 - 不要等 PMON,直接触发手动清理:
ALTER SYSTEM CHECKPOINT+ALTER SYSTEM FLUSH SHARED_POOL(后者可加速游标失效,间接促使临时段释放) - 若仍不释放,且数据库版本 ≥ 12c,可尝试
DBMS_SPACE_ADMIN.TEMP_TABLESPACE_DROP_SEGMENTS('TEMP')强制回收(需ADMINISTER DATABASE TRIGGER权限)
为什么切换默认临时表空间后原 TEMP 还删不掉
因为有会话仍以旧临时表空间为默认值在登录过程中(比如连接池维持着 session cached cursors),或者存在后台进程(如 SMCO、W00x)仍在引用旧 tempfile。直接 DROP TABLESPACE TEMP INCLUDING CONTENTS AND DATAFILES 会报 ORA-12906。
实操建议:
- 切换前先查依赖:
SELECT USERNAME, TEMPORARY_TABLESPACE FROM DBA_USERS WHERE TEMPORARY_TABLESPACE = 'TEMP',批量改用户默认临时表空间:ALTER USER xxx TEMPORARY TABLESPACE IRFS_TEMP - 确认无活跃会话用旧空间:
SELECT * FROM V$TEMPSEG_USAGE WHERE TABLESPACE = 'TEMP'必须为空 - 删表空间前加
RESTRICT模式:ALTER TABLESPACE TEMP OFFLINE→DROP TABLESPACE TEMP INCLUDING CONTENTS AND DATAFILES,避免被新连接抢占
临时表空间释放失败的核心不在“怎么缩”,而在“谁在用、为什么没退”。多数 case 的根因藏在 V$TEMPSEG_USAGE 和会话生命周期管理里,而不是单纯调大 autoextend 或重启实例。











