Goal
Sometimes, there are situations where the UNDO Tablespace starts growing unexpectedly.
So, how do you find out why?
Please note that the following queries only apply to Automatic Undo Management (AUM) where UNDO_MANAGEMENT is set to AUTO.
Fix
You can find out why the UNDO Tablespace starts growing unexpectedly, by running the following queries.
1.Use this query to confirm the Extent size and the total bytes for those Extent sizes for the Active UNDO Segments. This query will also confirm if there are too many extents of a particular size, that can lead to ORA-1628 "max # of extents" errors.
SELECT segment_name, bytes "Extent_Size", count(extent_id) "Extent_Count", bytes * count(extent_id) "Extent_Bytes" FROM dba_undo_extents WHERE status = 'ACTIVE' group by segment_name, bytes order by 1, 3 desc;
2.Then, use this query to identify those users who are using the Active AUM UNDO Segments.
10g: AUM Segment Name Format: _SYSSMUxidusn$
SELECT s.sid, s.serial#, s.username, u.segment_name, count(u.extent_id) "Extent Count", t.used_ublk, t.used_urec, s.program
FROM v$session s, v$transaction t, dba_undo_extents u
WHERE s.taddr = t.addr and u.segment_name = '_SYSSMU'||t.xidusn||'$' and u.status = 'ACTIVE'
GROUP BY s.sid, s.serial#, s.username, u.segment_name, t.used_ublk, t.used_urec, s.program
ORDER BY t.used_ublk desc, t.used_urec desc, s.sid, s.serial#, s.username, s.program;
11g: AUM Segment Name Format: _SYSSMUxidusn_number$
SELECT s.sid, s.serial#, s.username, u.segment_name, count(u.extent_id) "Extent Count", t.used_ublk, t.used_urec, s.program
FROM v$session s, v$transaction t, dba_undo_extents u
WHERE s.taddr = t.addr and u.segment_name like '_SYSSMU'||t.xidusn||'_%$' and u.status = 'ACTIVE'
GROUP BY s.sid, s.serial#, s.username, u.segment_name, t.used_ublk, t.used_urec, s.program
ORDER BY t.used_ublk desc, t.used_urec desc, s.sid, s.serial#, s.username, s.program;
3.Finally, use this query to identify those UNDO Segments that are being used by transactions rolling back.
select b.name "UNDO Segment Name", b.inst# "Instance ID", b.status$ STATUS, a.ktuxesiz "UNDO Blocks", a.ktuxeusn, a.ktuxeslt xid_slot, a.ktuxesqn xid_seq
from x$ktuxe a, undo$ b
where a.ktuxesta = 'ACTIVE' and a.ktuxecfl like '%DEAD%' and a.ktuxeusn = b.us#;
Once you have identified the different transactions using the Active UNDO Segments, you know the cause of the UNDO Tablespace usage.
If Active UNDO Segments are being used by transactions rolling back, then your options are;
1.Wait for the rollback to complete. The time to rollback will depend on the transaction mix i.e. SELECT, INSERT, UPDATE, DELETE. A SELECT needs very little/no time to rollback, but an INSERT, UPDATE or DELETE will need the same time to rollback, as it took to execute.
2.Perform a Database Point-In-Time Recovery. This means restoring the database from backup and recovering with the Redo logs, until just before the time the transaction rolling back started.