是的,普通排序操作在sql执行完毕且事务结束(commit/rollback)后,临时段立即被标记为free供重用,但磁盘空间不返还os;而lob操作产生的temporary lob_data段不会自动释放,需客户端显式调用ocilobfreetemporary或终止会话。

Oracle 临时表段(temporary segment)在绝大多数情况下会自动释放,但“自动”不等于“立即物理删除”,而是标记为空闲、可重用;真正不释放的场景往往和 LOB、长事务、异常会话或 SORT EXTENT POOL 状态异常有关。
事务提交或回滚后,临时排序段是否立刻释放?
是的,对于普通排序操作(如 ORDER BY、GROUP BY、HASH JOIN 等),只要对应会话完成该 SQL 执行且事务结束(COMMIT 或 ROLLBACK),Oracle 就会将使用的临时段标记为 FREE。注意:这只是逻辑释放 —— 磁盘空间不会返还给操作系统,只是加入 V$SORT_SEGMENT 的空闲 extent 池,供后续排序重用。
- 判断依据看
V$SORT_USAGE或V$TEMPSEG_USAGE视图是否还有该会话记录 - 如果 SQL 执行完但会话没断开,且没显式关闭游标(尤其 PL/SQL 中未
CLOSE游标),临时段可能仍被持有 -
ALTER SESSION SET WORKAREA_SIZE_POLICY = MANUAL且手动设了过大的SORT_AREA_SIZE,也可能延迟释放判断
全局临时表(GTT)的数据行什么时候消失?
取决于创建时指定的 ON COMMIT 子句:
-
ON COMMIT DELETE ROWS:每次COMMIT后,当前会话插入的 GTT 数据自动清空 -
ON COMMIT PRESERVE ROWS:数据保留到会话结束(DISCONNECT或进程终止)才清理 - 无论哪种,GTT 的段结构(table definition)本身是永久对象,不占 TEMP 表空间;只有插入的数据页才可能触发临时段分配(比如大 INSERT + 并行)
为什么有时 V$TEMPSEG_USAGE 里还残留着已“结束”的会话?
常见于以下三类情况,此时临时段未释放不是 bug,而是机制使然:
-
LOB 操作残留:应用通过 OCI/C 程序读取
CLOB/BLOB字段时,Oracle 内部会分配TEMPORARY LOB_DATA段,但不会主动释放 —— 它依赖客户端显式调用OCILobFreeTemporary()。若 C 程序没调或连接池长连接复用未清理,这些段就一直挂着 -
会话异常中断:如网络闪断、应用 crash,会话在 DB 端变成
INACTIVE但未真正断开,SMON 还没来得及回收(尤其 RAC 环境下跨实例协调延迟) -
SORT EXTENT POOL 异常:在高并发排序场景中,某个实例的 SORT EXTENT POOL LATCH 获取失败,导致已用 extent 未能及时标记 FREE,表现为
V$SORT_SEGMENT.USED_EXTENTS居高不下
如何验证临时段是否真的“卡住”了?
别只看表空间使用率,先查源头:
- 运行:
SELECT username, session_num, extents, segtype FROM v$tempseg_usage WHERE extents > 100;—— 找出大户 - 关联
v$session查sql_id和program:SELECT s.program, s.sql_id, t.extents FROM v$session s, v$tempseg_usage t WHERE s.saddr = t.session_addr; - 重点观察
segtype = 'LOB_DATA'的条目,这类基本不会自动释放,必须 kill 会话或让应用端清理 - 检查
V$SORT_SEGMENT:若USED_EXTENTS长期 > 0 且无活跃会话占用,说明 SORT EXTENT POOL 出问题,需用ALTER SESSION SET EVENTS 'immediate trace name DROP_SEGMENTS level <ts>';</ts>强制清理
临时段“自动释放”是常态,但它的实现高度依赖会话生命周期、客户端行为和内存池状态。最易被忽略的是 LOB 场景 —— 它根本不管事务边界,只认客户端显式释放。运维时盯着 V$TEMPSEG_USAGE 比盯着表空间报警更有价值。











