查TEMP表空间是否满,不能看dba_free_space,而应查DBA_TEMP_FREE_SPACE的FREE_SPACE列,并结合dba_temp_files中autoextensible状态;临时段未释放时可杀会话或执行ALTER TABLESPACE TEMP COALESCE合并碎片;根本解法是优化引发大量排序/哈希连接的SQL。
查TEMP表空间到底满没满,别光看“使用率”
ora-01652报错时,很多人第一反应是跑个select * from dba_free_space看空闲空间——但这是错的。临时表空间(temp)不走dba_free_space,它用的是v$temp_extent_pool和dba_temp_files。直接查dba_free_space会返回空或误导性结果,让你误判“还有空间”,其实早就耗尽了。
- 查真实空闲空间:用
SELECT * FROM DBA_TEMP_FREE_SPACE,重点关注FREE_SPACE列(单位字节) - 查每个临时文件大小和扩展状态:
SELECT file_name, bytes/1024/1024 AS size_mb, autoextensible, maxbytes/1024/1024 AS maxsize_mb FROM dba_temp_files - 如果
autoextensible是NO,哪怕FREE_SPACE显示有几百MB,只要下一个排序需要连续128个块(比如块大小8KB,就是1MB),就可能立刻报错
加空间不是只改SIZE,关键看AUTOEXTEND配得对不对
临时文件设成AUTOEXTEND ON NEXT 100M MAXSIZE UNLIMITED看似稳妥,但实际在高并发场景下容易引发IO争抢甚至挂起。更稳妥的做法是:先扩单次增长量(NEXT),再控上限,避免失控膨胀占满磁盘。
- 已存在文件开启自动扩展:
ALTER DATABASE TEMPFILE '/u01/oradata/db/temp01.dbf' AUTOEXTEND ON NEXT 256M MAXSIZE 8G - 新增文件更安全(对在线业务影响最小):
ALTER TABLESPACE TEMP ADD TEMPFILE '/u01/oradata/db/temp02.dbf' SIZE 4G AUTOEXTEND ON NEXT 128M MAXSIZE 16G - 切忌把
MAXSIZE设为UNLIMITED——万一某个SQL写错(比如笛卡尔积+全表扫描),可能几秒内打爆整个磁盘
临时段不释放?别急着重启库,先试试这三步
有时DBA_TEMP_FREE_SPACE显示空闲极少,但dba_temp_files里文件又没满,说明临时段被长期占用没释放。这不是磁盘空间问题,而是会话残留或SMON进程卡住。
- 查谁在吃临时段:
SELECT s.sid, s.username, u.tablespace, u.segtype, u.blocks*8/1024 AS mb_used FROM v$sort_usage u, v$session s WHERE u.session_addr = s.saddr ORDER BY u.blocks DESC - 若发现某会话
blocks极大且长时间不动,可杀掉:ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE - 强制合并空闲extent(不需重启):
ALTER TABLESPACE TEMP COALESCE——这个命令让SMON重新整理碎片,常能立刻腾出几百MB可用空间
SQL本身才是根因,别让扩容掩盖性能债
扩容只是止痛药。真正该盯的是报错SQL:一个没加限制的ORDER BY、多层嵌套子查询里的GROUP BY、或者两个大表做HASH JOIN,都可能单次消耗数GB临时空间。这类SQL在低峰期跑得过去,一到报表高峰期就必然触发ORA-01652。
- 用
v$sql_plan查执行计划里有没有SORT或HASH JOIN操作,特别关注TEMP_SPACE列(Oracle 12c+) - 加
/*+ USE_NL(t1,t2) */提示强制走嵌套循环,避开哈希连接;或加WHERE ROWNUM 快速验证是否数据量失控 - 生产环境上线前,必须对复杂报表SQL做
EXPLAIN PLAN+DBMS_XPLAN.DISPLAY检查临时空间预估
临时表空间的问题,表面是容量告警,背后往往是SQL质量、监控盲区和运维习惯的综合暴露。扩容操作5分钟能做完,但找出那个每晚2点准时吃掉3GB TEMP的SQL,可能要翻两小时AWR报告——这才是最不能跳过的步骤。

















