undo表空间持续增长不释放,大概率是长事务未提交或\_undo\_autotune自动调优机制覆盖了undo_retention参数,导致undo保留时间被动态拉高;应优先查v$undostat历史压力指标和v$transaction活跃事务,而非直接扩容或切换表空间。
undo表空间持续增长不释放,大概率不是空间真“用光了”,而是有事务卡住或自动调优机制在反向起作用——先别急着删文件或建新表空间。
查 v$undostat 看历史压力,别只盯当前占用率
当前 DBA_DATA_FILES 显示 UNDOTBS1 占用 95%,但这个数字没告诉你“为什么占着”。v$undostat 每 10 分钟一条记录,保留最近 4 天,才是诊断核心:
-
NOSPACEERRCNT > 0→ 已发生ORA-30036,必须立刻干预 -
MAXQUERYLEN持续大于UNDO_RETENTION→ 长查询强制保留旧版本,undo 被锁死 -
UNDOBLKS高 +TXNCOUNT低 → 单个事务极大(比如未分批的全表DELETE) -
NOSPACEERRCNT = 0且MAXQUERYLEN → 很可能只是长事务未提交,不是配置问题
执行这句快速看趋势:
SELECT BEGIN_TIME, UNDOBLKS, TXNCOUNT, MAXQUERYLEN, NOSPACEERRCNT FROM v$undostat ORDER BY BEGIN_TIME DESC FETCH FIRST 10 ROWS ONLY;
查 v$transaction 找真正在“吃” undo 的会话
很多 DBA 直接切表空间,结果新表空间几分钟后也涨满——因为同一个长事务还在跑。关键字段是 used_ublk 和 idle_mins:
-
idle_mins > 5且used_ublk > 10000→ 极可能挂起(应用忘记COMMIT或被阻塞) -
username是业务账号(非SYSTEM/DBA)→ 找对应开发确认逻辑 -
osuser/machine指向某台应用服务器 → 可临时重启该连接池,而非杀会话
别漏掉关联 v$session 查来源:
SELECT s.sid, s.serial#, s.username, s.osuser, s.machine,
t.start_time, t.used_ublk, (SYSDATE - t.start_time) * 24 * 60 idle_mins
FROM v$transaction t
JOIN v$session s ON s.taddr = t.addr
ORDER BY t.start_time;
小心 _undo_autotune 自动调优把 UNDO_RETENTION 给“覆盖”了
Oracle 10.2+ 默认开启 _undo_autotune=true,它会无视你手动设的 undo_retention,按实际负载动态拉高保留时间——尤其当 undo 表空间非自动扩展时,为防 ORA-01555,它可能把 tuned_undoretention 推到几小时甚至一天。
- 查当前是否生效:
SELECT tuned_undoretention FROM v$undostat WHERE rownum = 1; - 如果远高于你设的
undo_retention,且磁盘紧张,可关掉:ALTER SYSTEM SET "_undo_autotune"=FALSE SCOPE=BOTH; - 关之前确认:数据库版本 ≥ 10.2.0.4(老版本关了可能触发 bug 5387030)
注意:_undo_autotune 关闭后,undo_retention 才真正生效;但若表空间没开 AUTOEXTEND,仍可能因空间不足被迫延长保留时间。
切换 undo_tablespace 前必须确认旧表空间已 OFFLINE
执行 ALTER SYSTEM SET undo_tablespace=UNDOTBS2 后,旧 UNDOTBS1 的 rollback segment 不会立刻下线。强行删数据文件会报 ORA-30013。
- 查状态:
SELECT tablespace_name, status FROM dba_tablespaces WHERE tablespace_name = 'UNDOTBS1';—— 必须是OFFLINE - 查回滚段:
SELECT segment_name, status FROM dba_rollback_segs WHERE tablespace_name = 'UNDOTBS1';—— 全部应为OFFLINE - 等不到?说明还有活跃事务或系统进程在用它,此时切表空间无意义,得先处理源头
最常被忽略的一点:RAC 环境下,要逐个实例确认;PDB 环境下,必须 ALTER SESSION SET CONTAINER=pdb 后再查,否则看到的是 CDB 层状态。











