ORA-01652本质是TEMP表空间缺乏≥128个extent的连续空闲段,非磁盘物理耗尽;应查v$temp_extent_pool和v$sort_segment定位真实使用量,结合dba_temp_files确认autoextensible状态,再通过resize、add tempfile或autoextend扩容,并用coalesce合并碎片。

临时表空间耗尽不会直接导致“全库只读”,但会引发 ORA-01652,阻塞大量查询和批处理,严重时让业务系统看起来像“卡死”或“不可写”——这是误判的高发点。真正让数据库进入只读状态的是人为执行 ALTER DATABASE OPEN READ ONLY 或备库角色切换,不是 TEMP 满了。
为什么 TEMP 耗尽会让系统“像只读”一样瘫痪
临时表空间不存业务数据,但几乎所有写操作的配套动作都依赖它:建索引、收集统计信息(DBMS_STATS)、物化视图刷新、分区交换、甚至 INSERT /*+ APPEND */ 的 direct-path load。一旦报 ORA-01652,这些操作全部失败,DBA 一查发现“啥都干不了”,容易下意识以为库被锁死了。
-
SELECT ... FOR UPDATE本身不写 TEMP,但如果语句带ORDER BY或GROUP BY,仍可能触发排序溢出,进而失败 - DBA 执行
ANALYZE TABLE或DBMS_STATS.GATHER_TABLE_STATS时,若目标表在只读表空间中,部分内部元数据访问会尝试写 TEMP,也可能被拦住 - RMAN 备份不直读 TEMP,但
BACKUP VALIDATE或某些恢复前检查会间接依赖临时段分配逻辑,偶发卡住
TEMP 表空间不能靠“设 quota”来限制
QUOTA 只对永久表空间(如 USERS)生效,对 TEMP 完全无效。试图写 ALTER USER u1 QUOTA 100M ON temp 会直接报错 ORA-02301。临时段由实例统一管理,按需分配,用户级配额无意义。
- 真正能控速的是
Resource Manager:绑定consumer_group,限制该组的PGA_AGGREGATE_LIMIT和并行度,从源头减少溢出概率 - 临时表空间本身要支持自动扩展(
AUTOEXTEND ON),但必须设MAXSIZE防止无限增长撑爆磁盘;别用UNLIMITED - 不要把多个应用共用一个
TEMP;可为 ETL、报表、OLTP 分别建专用临时表空间,并通过ALTER USER ... TEMPORARY TABLESPACE绑定
如何快速定位谁在吃掉 TEMP 空间
别急着加文件,先看是不是某个 SQL 在疯狂刷盘。关键视图是 V$SORT_USAGE 和 V$TEMPSEG_USAGE(12c+ 推荐后者):
SELECT s.sid, s.serial#, s.username, t.sql_id, t.blocks * 8 / 1024 AS mb_used FROM v$tempseg_usage t JOIN v$session s ON t.session_addr = s.saddr WHERE t.tablespace = 'TEMP' ORDER BY t.blocks DESC;
- 查到
sql_id后,立刻用SELECT * FROM v$sql WHERE sql_id = 'xxx'看原始语句 - 结合
V$SQL_PLAN看执行计划里是否有SORT、HASH JOIN或WINDOW SORT,且BYTES列极大 - 注意:
V$TEMPSEG_USAGE显示的是当前活跃使用量,不是历史峰值;临时段释放后记录就消失,得实时抓
临时表空间满了,但 ALTER TABLESPACE READ ONLY 不起作用?
因为 READ ONLY 是针对**永久表空间**的命令,对 TEMP 表空间执行 ALTER TABLESPACE temp READ ONLY 会直接报错 ORA-01643(表空间必须是永久类型)。临时表空间天生就是“只用于临时”的,没有只读/读写之分。
- 想让某类操作不碰 TEMP?只能改 SQL:加索引消除排序、重写
GROUP BY为ROLLUP减少中间集、用物化视图预计算 - 想隔离风险?建独立临时表空间 +
Resource Manager限流,比寄希望于“只读”靠谱得多 - 最常被忽略的一点:归档日志路径如果和 TEMP 文件放在同一磁盘,TEMP 带来的 I/O 峰值可能拖垮归档进程,间接导致
ARCHIVE LOG FULL,最终触发数据库挂起——这比 TEMP 满更隐蔽











