undo段本身不会被锁定,但未提交事务会持续占用active状态的undo extents,使对应undo segment保持online状态;需通过v$rollstat.xacts>0定位活跃回滚段,再关联v$transaction和v$session找出拖慢undo释放的会话。

直接结论:UNDO段本身不会被“锁定”,但未提交事务会持续占用并持有 ACTIVE 状态的 UNDO extents,进而让对应 UNDO segment 保持 ONLINE 状态——你要找的其实是这些“被活事务钉住”的回滚段。
查哪些 UNDO 段正被未提交事务使用
关键看 v$rollstat 和 dba_rollback_segs 的关联结果,结合 v$transaction 确认活跃事务归属:
-
v$rollstat.usn是回滚段编号,dba_rollback_segs.segment_id与之对应 - 如果
v$rollstat.xacts > 0,说明该回滚段当前有活跃事务(即未提交) -
v$transaction中的xidusn字段就是它所用的回滚段编号,可反向验证
执行这个查询能快速定位:
SELECT r.segment_name, r.status, v.xacts, v.rssize/1024/1024 mb_used FROM dba_rollback_segs r, v$rollstat v WHERE r.segment_id = v.usn AND v.xacts > 0 ORDER BY v.xacts DESC;
为什么不能只查 DBA_UNDO_EXTENTS.STATUS = 'ACTIVE'?
因为 DBA_UNDO_EXTENTS.STATUS = 'ACTIVE' 表示该 extent 正被未提交事务使用,但它不告诉你属于哪个回滚段——同一个 UNDO segment 下可能混着 ACTIVE / UNEXPIRED / EXPIRED 多种状态的 extent。你真正要干预的是“源头”:那个被事务绑定的回滚段本身。
- 只查
DBA_UNDO_EXTENTS容易漏掉段级信息(比如段名、状态 ONLINE/OFFLINE) -
dba_rollback_segs.status为ONLINE或PENDING OFFLINE才代表它正在服务事务 -
OFFLINE的段哪怕还有UNEXPIREDextent,也不再接受新事务
如何确认是哪个会话在拖着 UNDO 不释放
从回滚段顺藤摸瓜到具体会话,靠 v$transaction 和 v$session 关联:
-
v$transaction.xidusn对应回滚段编号,v$transaction.ses_addr是会话地址 -
v$session.saddr与之连接后,就能拿到sid、serial#、username、sql_id、logon_time - 特别注意
v$session.status:若为INACTIVE且logon_time很早,极可能是“挂起事务”(比如应用断连但没 rollback)
常用诊断语句:
SELECT s.sid, s.serial#, s.username, s.status, s.sql_id, t.start_time, t.used_ublk FROM v$session s, v$transaction t WHERE s.saddr = t.ses_addr ORDER BY t.start_time;
容易忽略的关键点
UNDO 段不是锁对象,但它的生命周期完全由事务驱动;一个长时间未提交的事务,会让整个回滚段无法 offline,进而影响 UNDO 表空间自动回收——尤其当 UNDO_RETENTION 设置偏高、或表空间非 autoextend 时,这种“钉子事务”会直接触发 ORA-30036: unable to extend segment 错误。
别只盯着 DBA_UNDO_EXTENTS 数行数,先用 v$rollstat.xacts 找出真正在干活的段,再顺下去揪会话。否则你看到的可能只是“历史残留”,而非问题根源。











