ORA-01548 & drop Undo tablespace
Recently I was cloning one RAC database to single instance database, and afterwards I wanted to remove one of the Undo tablespaces. Unfortunately, it didn’t go so smoothly as I expected…
SQL> drop tablespace UNDOTBS2 including contents and datafiles; * ERROR at line 1: ORA-01548: active rollback segment '_SYSSMU39_1583257383$' found, terminate dropping tablespace
Hmmm, ok – let’s check why:
SQL> select segment_name,status from dba_rollback_segs where tablespace_name = 'UNDOTB2' and status != 'OFFLINE';
SEGMENT_NAME STATUS
------------------------------ ----------------------------------------------------------------
_SYSSMU39_1583257383$ PARTLY AVAILABLE
_SYSSMU40_2790682469$ PARTLY AVAILABLE
_SYSSMU64_2312563332$ PARTLY AVAILABLE
_SYSSMU72_370900394$ PARTLY AVAILABLE
_SYSSMU79_210856562$ PARTLY AVAILABLE
_SYSSMU186_2826375952$ PARTLY AVAILABLE
_SYSSMU193_3230612747$ PARTLY AVAILABLE
7 rows selected.
SQL> SELECT KTUXEUSN, KTUXESLT, KTUXESQN, /* Transaction ID */
KTUXESTA Status,
KTUXECFL Flags
FROM x$ktuxe
WHERE ktuxesta!='INACTIVE';
KTUXEUSN KTUXESLT KTUXESQN STATUS FLAGS
---------- ---------- ---------- ---------------- ------------------------
39 8 1790801 PREPARED SCO|COL|REV|DEAD|EXTDTX
40 14 3007703 PREPARED SCO|COL|REV|DEAD|EXTDTX
64 21 1766227 PREPARED SCO|COL|REV|DEAD|EXTDTX
72 28 3720950 PREPARED SCO|COL|REV|DEAD|EXTDTX
79 30 1263186 PREPARED SCO|COL|REV|DEAD|EXTDTX
186 0 381814 PREPARED SCO|COL|REV|DEAD|EXTDTX
193 26 471483 PREPARED SCO|COL|REV|DEAD|EXTDTX
7 rows selected.
SQL> col GLOBAL_TRAN_ID for a30
SQL> SELECT LOCAL_TRAN_ID,GLOBAL_TRAN_ID,STATE,MIXED,COMMIT# FROM DBA_2PC_PENDING
LOCAL_TRAN_ID GLOBAL_TRAN_ID STATE MIXED COMMIT#
---------------------- ------------------------------ ---------------- ------------ ----------------
64.21.1766227 48801.4B6F90FDD3B111E02D21 prepared no 8444206153031
79.30.1263186 48801.144C46F922F511E02D21 prepared no 8458822851795
39.8.1790801 48801.76CC934FA73211E02D21 prepared no 8458821251112
40.14.3007703 48801.76D6934FA73211E02D21 prepared no 8458821251099
72.28.3720950 48801.76C8934FA73211E02D21 prepared no 8458821250987
193.26.471483 48801.76CE934FA73211E02D21 prepared no 8458821250807
186.0.381814 48801.76D0934FA73211E02D21 prepared no 8458821251271
7 rows selected.
SQL> SELECT LOCAL_TRAN_ID,IN_OUT,DATABASE,INTERFACE FROM dba_2pc_neighbors;
LOCAL_TRAN_ID IN_OUT DATABASE I
---------------------- ------------ ----------- -
64.21.1766227 in jdbc_3 N
64.21.1766227 in jdbc_22 N
79.30.1263186 in jdbc_10 N
79.30.1263186 in jdbc_49 N
39.8.1790801 in jdbc_10 N
39.8.1790801 in jdbc_46 N
40.14.3007703 in jdbc_56 N
40.14.3007703 in jdbc_44 N
72.28.3720950 in jdbc_44 N
72.28.3720950 in jdbc_22 N
193.26.471483 in jdbc_4 N
193.26.471483 in jdbc_52 N
186.0.381814 in jdbc_28 N
186.0.381814 in jdbc_41 N
14 rows selected.
Well, there were some “zombie” transactions around…
Because I don’t know how that happened, I’ll provide you only the solution how to remove such dead transactions:
set serveroutput on
alter system disable distributed recovery;
begin
for rec in (SELECT KTUXEUSN ||'.'|| KTUXESLT ||'.'|| KTUXESQN as local_trx_id /* Transaction ID */
FROM x$ktuxe
WHERE ktuxesta!='INACTIVE'
)
loop
set transaction use rollback segment SYSTEM;
delete from sys.pending_trans$ where local_tran_id = rec.local_trx_id;
delete from sys.pending_sessions$ where local_tran_id = rec.local_trx_id;
delete from sys.pending_sub_sessions$ where local_tran_id = rec.local_trx_id;
--commit;
insert into pending_trans$ (
LOCAL_TRAN_ID, GLOBAL_TRAN_FMT, GLOBAL_ORACLE_ID, STATE, STATUS, SESSION_VECTOR,RECO_VECTOR, TYPE#, FAIL_TIME,RECO_TIME)
values( rec.local_trx_id, 306206, /* */
'XXXXXXX.12345.1.2.3', 'prepared','P', hextoraw( '00000001' ), hextoraw( '00000000' ),0, sysdate, sysdate );
insert into pending_sessions$
values( rec.local_trx_id, 1, hextoraw('05004F003A1500000104'), 'C', 0, 30258592, '', 146);
commit;
EXECUTE IMMEDIATE 'commit force '''|| rec.local_trx_id ||'''';
DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY(rec.local_trx_id);
commit;
end loop;
exception
when others then
dbms_output.put_line(sqlerrm);
end;
/
alter system enable distributed recovery;
Finally, I was able to drop the UNDOTBS2 tablespace:
SQL> select segment_name,status from dba_rollback_segs where tablespace_name = 'UNDOTB2' and status != 'OFFLINE'; no rows selected SQL> drop tablespace UNDOTBS2 including contents and datafiles; Tablespace dropped.
Hope it helps someone.
