oracle 19c中temp空间“假性耗尽”的主因是临时blob/clob操作后未释放temporary lob_data段,该段绑定会话、不随sql结束释放,仅在会话断开或显式调用dbms_lob.freetemporary时才清理,且不反映在dba_temp_free_space中,导致resize失败和监控误判。

直接操作临时BLOB会持续占用TEMP空间,且不随SQL执行结束自动释放——这是Oracle 19c及以后版本中TEMP表空间“假性耗尽”的最常见隐形原因。
临时BLOB在v$sort_usage里显示为 TEMPORARY LOB_DATA
当Java/C程序通过长连接执行含CLOB/BLOB字段的查询,并叠加ORDER BY或GROUP BY时,Oracle会在TEMP表空间中分配TEMPORARY LOB_DATA段。这类段:
- 不会出现在
v$sort_usage的segtype = 'SORT'行里,而是单独标记为contents = 'TEMPORARY LOB_DATA',极易被DBA忽略 - 生命周期绑定会话,语句执行完也不释放,直到会话断开或显式调用
DBMS_LOB.FREETEMPORARY - 占用空间计入
v$temp_space_header.free_blocks,但dba_temp_free_space和dba_temp_files完全不反映这部分消耗
为什么alter database tempfile resize会失败
即使你看到dba_temp_files显示还有50GB空闲,alter database tempfile '/path/to/temp01.dbf' resize 2g仍可能报ORA-03297。因为:
- 临时文件高位(high water mark)存在未释放的
TEMPORARY LOB_DATA区(extent),哪怕只占几KB -
resize要求文件末尾全部空闲,而LOB临时段往往“钉”在文件末尾附近 -
alter tablespace TEMP shrink space对临时表空间无效,会直接报错
DBMS_LOB.FREETEMPORARY必须由应用层显式调用
Oracle不会替你清理临时LOB,必须由应用代码主动释放:
- Java JDBC中:调用
oracle.sql.BLOB.free()或oracle.sql.CLOB.free() - PL/SQL中:对
DBMS_LOB.CREATETEMPORARY创建的LOB,必须配对使用DBMS_LOB.FREETEMPORARY - 如果应用用的是ORM(如MyBatis、Hibernate),需确认其是否封装了
free()调用;很多老版本默认不调用
重建TEMP表空间是唯一能立即见效的兜底手段
当确认存在大量TEMPORARY LOB_DATA残留时,重建比“杀会话+coalesce”更可靠:
- 新建临时表空间:
create temporary tablespace temp2 tempfile '/u01/oradata/ORCL/temp02.dbf' size 1024m autoextend on next 100m maxsize 8g - 切换默认:
alter database default temporary tablespace temp2 - 检查残留:
select sid, serial#, username from v$session where tempseg_used > 0 and tablespace = 'TEMP'—— 结果必须为空 - 删除旧表空间:
drop tablespace temp including contents and datafiles(缺including contents会失败)
注意:临时表空间不能“空着”,删掉最后一个tempfile后立刻执行排序就会触发ORA-01652——所以切换必须原子完成,不能留空窗期。











