SMON仅在数据库启动、临时表空间扩展或每5分钟轮询时触发清理,且需获取ST锁;受长事务、分布式事务挂起或并行查询残留影响,会等待或跳过,导致临时段延迟释放。
smon 不会自动清理“过期”临时段——它只在固定时机扫描并回收真正空闲的段,且受锁、事务状态和表空间类型严格限制。
SMON 什么时候才会触发临时段清理
SMON 的清理不是持续运行的守护线程,而是事件驱动+定时轮询:
- 数据库启动时强制全量扫描并合并空闲区
- 临时表空间发生扩展(如
ALTER TABLESPACE TEMP ADD TEMPFILE)时顺带检查 - 每 5 分钟一次后台轮询(由隐含参数
_smu_debug_mode控制频率,不可调) - 仅对本地管理(LMT)的临时表空间生效;字典管理(DMT)已弃用且不支持自动合并
这意味着:即使一个会话已断开超 2 小时,只要 SMON 还没轮到这次扫描,V$TEMPSEG_USAGE 里仍可能显示其残留记录——这不是 bug,是设计如此。
为什么你看到的“未释放临时段”大概率不是真问题
先别急着干预,区分三类常见假阳性:
-
V$TEMPSEG_USAGE中的记录对应V$SESSION.STATUS = 'INACTIVE'且LAST_CALL_ET > 3600:可能是僵死会话,但需确认其SPID是否仍在 OS 层存活(ps -p <spid></spid>) -
V$SORT_SEGMENT.USED_EXTENTS = 0:这是已释放但未从数据字典清除的“幽灵段”,只能等 SMON 下次扫描抹除,无法人工干预 - 临时文件(
tempfile)大小长期 100% 占用:Oracle 不自动收缩 tempfile,DBA_TEMP_FREE_SPACE显示已用 100% ≠ 真实无空闲块,要看V$TEMP_SPACE_HEADER.FREE_BLOCKS
如何让 SMON “尽快”执行清理
没有直接命令叫“触发 SMON 清理”,但可通过以下方式诱导它立即介入:
- 执行
ALTER TABLESPACE TEMP COALESCE:强制 SMON 合并相邻空闲 extent,过程中会顺带识别并回收可重用段(仅限 LMT) - 微调表空间 storage 参数:
ALTER TABLESPACE TEMP INCREASE 1再ALTER TABLESPACE TEMP INCREASE 0,模拟一次扩展行为,触发检查 - 启用诊断事件(慎用):
ALTER SESSION SET EVENTS 'immediate trace name DROP_SEGMENTS level <ts>'</ts>,其中ts#来自SELECT TS# FROM SYS.TS$ WHERE NAME='TEMP';该操作绕过 SMON 锁等待逻辑,但仅对明确标记为可回收的段有效
注意:DROP_SEGMENTS 事件不会清理因分布式事务挂起(DBA_2PC_PENDING 非空)或长事务阻塞导致的段,这类必须先解决源头问题。
最容易被忽略的清理前提
所有手动诱导手段都建立在一个关键事实上:SMON 清理前必须获取 ST(System Transaction)锁。如果此时存在:
- 未提交/回滚的分布式事务(查
DBA_2PC_PENDING) - 异常终止的并行查询残留(
V$PX_PROCESS中有 orphaned 进程) - 持有
ST锁未释放的长事务(查V$TRANSACTION中START_TIME极早的记录)
SMON 会跳过该表空间或无限等待——此时任何 COALESCE 或事件触发都无效。真正要做的,是先定位并清理这些阻塞源,而不是反复折腾 TEMP 表空间本身。











