查真实空闲空间应使用DBA_TEMP_FREE_SPACE的FREE_SPACE列(单位字节),而非DBA_FREE_SPACE;若FREE_SPACE接近0即真耗尽,需新增临时文件、杀占用会话并COALESCE释放碎片,同时优化SQL减少排序/哈希溢出。
查真实空闲空间别用 DBA_FREE_SPACE
看到 ora-01652 就去查 dba_free_space,结果发现“还有 2gb 空闲”,然后一脸懵——这是典型误判。dba_free_space 对临时表空间完全无效,它只管永久表空间。你看到的数字根本不能用来判断 temp 能不能分配新段。
真正该看的是:DBA_TEMP_FREE_SPACE 里的 FREE_SPACE 列(单位字节):
SELECT TABLESPACE_NAME, FREE_SPACE/1024/1024 AS FREE_MB FROM DBA_TEMP_FREE_SPACE;
如果 FREE_MB 接近 0,说明真没连续空间了;如果还有几百 MB 却报错,问题大概率不在容量,而在碎片或会话卡住。
加新 TEMPFILE 比扩旧文件更稳
在线业务怕抖动,RESIZE 或给已有 TEMPFILE 开 AUTOEXTEND ON 可能触发 IO 尖峰甚至短暂挂起。新增一个文件是最小干扰方案:
ALTER TABLESPACE TEMP ADD TEMPFILE '/u01/oradata/db/temp02.dbf' SIZE 4G AUTOEXTEND ON NEXT 128M MAXSIZE 16G;- 绝对别写
MAXSIZE UNLIMITED:一个没加限制的笛卡尔积 SQL,3 秒就能打爆整块盘 - 已有文件开启自动扩展要慎用:
ALTER DATABASE TEMPFILE '/u01/oradata/db/temp01.dbf' AUTOEXTEND ON NEXT 256M MAXSIZE 8G;
杀残留会话 + COALESCE 才能清碎片
DBA_TEMP_FREE_SPACE.FREE_SPACE 极低,但 DBA_TEMP_FILES.BYTES 没满?说明临时段被长期占用没释放,不是磁盘问题,是会话或 SMON 卡住。
先定位谁在吃空间:
SELECT s.sid, s.username, u.segtype, u.blocks*8/1024 AS MB_USED FROM v$sort_usage u JOIN v$session s ON u.session_addr = s.saddr ORDER BY u.blocks DESC;
找到长时间不动、占用上百 MB 的会话,直接杀:
ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;- 再执行:
ALTER TABLESPACE TEMP COALESCE;—— 合并碎片,无需重启
排序失败的根因往往在 SQL,不在 TEMP
ORA-01652 是症状,不是病根。90% 的爆发来自少数几个 SQL:含 ORDER BY、GROUP BY、哈希连接、或重建大索引。
查执行计划重点盯两处:
-
OPERATION列是否有SORT ORDER BY、HASH JOIN、SORT GROUP BY -
TempSpc列是否显示几百 MB 甚至几 GB —— 这说明它本就不该走磁盘排序
优化方向比扩容更治本:加索引覆盖排序字段、改写为分页嵌套循环、避免全表哈希连接后大排序。临时调大 PGA_AGGREGATE_TARGET 可缓解,但掩盖不了 SQL 设计缺陷。
临时表空间的问题从来不是“够不够大”,而是“有没有被某条 SQL 霸占着不放”或者“有没有连续空间可分配”。查错时先看 DBA_TEMP_FREE_SPACE 和 v$sort_usage,别被假空闲迷惑;扩容时优先加文件,别碰已有 TEMPFILE 的 RESIZE;最要紧的是,别让开发把 ORDER BY 往大数据集上硬套——那才是真正的定时炸弹。











