临时表空间IO和使用峰值可通过AWR报告中“Tablespace IO Stats”(关注Av Writes/s>50/s且Av Wr(ms)>10ms)和“Wait Events”(direct path write/read temp进入Top 3且总等待>30秒)交叉判断。
怎么看临时表空间的IO和使用峰值?
临时表空间压力最直接的表现是 temp 表空间所在数据文件的 io 等待高、读写延迟大,或会话频繁等待 direct path write temp 和 direct path read temp。awr 报告里不直接显示“临时表空间用了多少”,得从两个地方交叉看:
- 「Tablespace IO Stats」部分找
TEMP(或你自定义的临时表空间名)对应的数据文件,重点关注Av Reads/s、Av Writes/s和Av Rd(ms)/Av Wr(ms)—— 如果平均写延迟 > 10ms 且写次数持续高于 50/s,基本可以断定 IO 瓶颈存在 - 「Wait Events」部分筛出前 5 的等待事件,若
direct path write temp或direct path read temp排进 Top 3,尤其在报告周期内总等待时间 > 30 秒,说明排序/哈希操作大量落盘,临时空间已成瓶颈
怎么定位哪些 SQL 在疯狂用 TEMP?
AWR 本身不记录每条 SQL 的临时段使用量,但可以通过 DBA_HIST_SQLSTAT 结合 temp_space_allocated 字段反查 —— 注意这个字段只在 Oracle 10gR2+ 且启用了 STATISTICS_LEVEL = TYPICAL 或 ALL 时才被采集。
- 查过去一小时 temp 消耗最多的 SQL:
SELECT sql_id, temp_space_allocated/1024/1024/1024 gb_used<br>FROM dba_hist_sqlstat<br>WHERE snap_id IN (SELECT snap_id FROM dba_hist_snapshot WHERE begin_interval_time > SYSDATE - 1/24)<br>AND temp_space_allocated > 0<br>ORDER BY temp_space_allocated DESC<br>FETCH FIRST 5 ROWS ONLY;
- 如果查不到结果,大概率是
STATISTICS_LEVEL被设成了BASIC,此时只能退回到实时视图V$SQL查当前活跃语句:SELECT sql_id, sql_text, temp_space_allocated FROM v$sql WHERE temp_space_allocated > 1073741824 ORDER BY temp_space_allocated DESC;
为什么有的排序不走 TEMP 却还在等 temp 相关事件?
常见误解:只要没显式建临时表,就不会压临时表空间。其实 Oracle 的排序(ORDER BY)、哈希连接(HASH JOIN)、位图合并(BITMAP MERGE)等操作都依赖 PGA 中的 sort_area_size / workarea_size_policy,一旦 PGA 不够,就会 spill 到 TEMP。而 direct path write temp 等待不一定来自大 SQL,也可能源于大量并发小排序(比如应用层分页查询 + ORDER BY)。
- 检查是否 PGA 设置过小:
SELECT name, value FROM v$parameter WHERE name IN ('pga_aggregate_target', 'workarea_size_policy');若workarea_size_policy = AUTO但pga_aggregate_target小于物理内存的 20%,容易触发频繁 spill - 查当前正在 spill 的会话:
SELECT sid, sql_id, operation_type, policy, last_memory_used, tempseg_size FROM v$sql_workarea_active;其中tempseg_size > 0表示已落盘,policy = 'AUTO'且last_memory_used接近estimated_optimal_size说明刚好卡在临界点
临时表空间爆满后,如何快速释放空间而不杀会话?
临时表空间文件不会自动收缩,即使排序结束,已分配的区(extent)仍被标记为“已使用”,直到实例重启或执行清理动作。别急着 ALTER DATABASE TEMPFILE ... DROP INCLUDING DATAFILES —— 这会中断所有使用该 tempfile 的会话。
- 先确认哪些 tempfile 是空闲的:
SELECT file_name, tablespace_name, bytes/1024/1024 mb_total, user_bytes/1024/1024 mb_used FROM dba_temp_files;注意user_bytes是已分配给用户的大小,不是当前实际使用量 - 真正释放空间要靠清空“已分配但未释放”的临时段:
ALTER TABLESPACE temp COALESCE;(适用于 LMT 本地管理临时表空间);如果是旧版字典管理,需用ALTER DATABASE RECOVER TEMPFILE ...配合归档日志(极少用) - 更稳妥的做法是加一个新 tempfile 并设为默认:
ALTER TABLESPACE temp ADD TEMPFILE '/u01/oradata/db/temp02.dbf' SIZE 2G AUTOEXTEND ON NEXT 100M MAXSIZE 10G;再运行ALTER DATABASE DEFAULT TEMPORARY TABLESPACE temp;,让新会话优先使用新文件
临时段的空间回收机制和普通表空间完全不同,它不依赖 DBWR,也不走 checkpoint,靠的是 SMON 定期扫描和会话退出时的隐式释放——所以高峰期看到 user_bytes 居高不下,未必是真满了,可能只是有长事务或异常断连的会话残留了临时段。











