Oracle刪除資料表空間遇到的問題及解決
問題1:刪除資料表空間期間遭遇報錯 ORA-29857
刪除資料表空間語句:DROP TABLESPACE SAC INCLUDING CONTENTS AND DATAFILES;
根據MOS文檔:
How To Resolve ORA-29857 During a Drop Tablespace although No Domain Index exists in This Tablespace (文檔 ID 1610456.1)
對於ORA-29857這個錯誤,文檔說的很清楚:
現象:
刪除資料表空間時,遇到報錯ORA-29857,例如:
SQL> drop tablespace SAC including contents and datafiles
drop tablespace SAC including contents and datafiles*ERROR at line 1:ORA-29857: domain indexes and/or secondary objects exist in the tablespace
然而,你並未在這個資料表空間中發現域索引:
SQL> SELECT OWNER,INDEX_NAME, TABLE_OWNER, TABLE_NAME FROM DBA_INDEXES WHERE INDEX_TYPE='DOMAIN' AND TABLESPACE_NAME ='SAC';no rows selected
原因:
The table which is in the tablespace to be dropped has a domain index which needs to be dropped before dropping the tablespace.
Domain indexes cannot be created in a specific tablespace and the TABLESPACE_NAME column in DBA_INDEXES is always null for domain indexes.
要刪除的資料表空間中的表有一個域索引,這個域索引在刪除資料表空間前需要被刪除掉。
域索引不能被建立在指定的資料表空間,對於域索引,DBA_INDEXES中的TABLESPACE_NAME列值總是空值。
解決方案:
You need to identify and drop the secondary objects:
你需要找出並刪除二級對象:
1.The domain index associated with a table in the tablespace to be dropped can be identified from the following query:
要刪除的與在這個資料表空間中的表相關的域索引可以通過下面的查詢找出來:
SQL> SELECT INDEX_NAME,I.TABLE_NAME FROM DBA_INDEXES I, DBA_TABLES T WHERE T.TABLE_NAME=I.TABLE_NAME AND T.OWNER=I.OWNERAND I.INDEX_TYPE='DOMAIN'and t.TABLESPACE_NAME='&TABLESPACE_NAME';
2.Secondary objects associated with domain indexes, can be identified from the following query:
與域索引相關的二級對象,可以通過下面的查詢找出來:
SQL> SELECT SECONDARY_OBJECT_OWNER,SECONDARY_OBJECT_NAME,SECONDARY_OBJDATA_TYPE FROM DBA_SECONDARY_OBJECTS WHERE INDEX_NAME='INDEX_NAME_From_Previous_Query';
Once you identify the secondary objects, you can drop those and then drop the tablespace.
一旦你找出這些二級對象,你就可以刪除它們然後再刪除資料表空間。
Please see the following example:
請看下面的例子:
SQL> CREATE TABLESPACE SAC DATAFILE 'C:\SAC.DBF' SIZE 50M;Tablespace created.SQL> CREATE TABLE SAC TABLESPACE SAC AS SELECT * FROM ALL_OBJECTS;Table created.SQL> begin ctx_ddl.create_preference('SUBSTRING_PREF','BASIC_WORDLIST'); ctx_ddl.set_attribute('SUBSTRING_PREF', 'SUBSTRING_INDEX','TRUE'); end; /PL/SQL procedure successfully completed.-- Trying to create the domain index in specific tablespace fails with ORA-29850:SQL> CREATE INDEX SAC_INDX ON SAC(OBJECT_TYPE) INDEXTYPE IS CTXSYS.CONTEXT PARAMETERS ('WORDLIST SUBSTRING_PREF MEMORY 50M') TABLESPACE SAC;CREATE INDEX SAC_INDX ON SAC(OBJECT_TYPE) INDEXTYPE IS CTXSYS.CONTEXT PARAMETERS ('WORDLIST SUBSTRING_PREF MEMORY 50M') TABLESPACE SAC*ERROR at line 1:ORA-29850: invalid option for creation of domain indexesSQL> CREATE INDEX SAC_INDX ON SAC(OBJECT_TYPE) INDEXTYPE IS CTXSYS.CONTEXT PARAMETERS ('WORDLIST SUBSTRING_PREF MEMORY 50M');Index created. SQL> drop tablespace sac including contents and datafiles;drop tablespace sac including contents and datafiles*ERROR at line 1:ORA-29857: domain indexes and/or secondary objects exist in the tablespace-- Trying to find the domain index in this tablespace:SQL> SELECT OWNER,INDEX_NAME, TABLE_OWNER, TABLE_NAME FROM DBA_INDEXES WHERE INDEX_TYPE='DOMAIN' AND TABLESPACE_NAME ='SAC';no rows selected--Trying to find segments created in this newly created tablespace:SQL> SELECT SEGMENT_NAME,SEGMENT_TYPE FROM DBA_SEGMENTS WHERE TABLESPACE_NAME='SAC';SEGMENT_NAME SEGMENT_TYPE-------------------- ------------------SAC TABLE-- Trying to find the segment for index SAC_INDX :SQL> SELECT TABLESPACE_NAME FROM DBA_SEGMENTS WHERE SEGMENT_NAME='SAC_INDX';no rows selected-- Trying to find the tablespace for index SAC_INDX from DBA_INDEXES :SQL> set null nullSQL> select INDEX_TYPE,TABLE_TYPE,DOMIDX_STATUS,DOMIDX_OPSTATUS,SEGMENT_CREATED,TABLESPACE_NAME from DBA_INDEXES where INDEX_NAME='SAC_INDX';INDEX_TYPE TABLE_TYPE DOMIDX_STATU DOMIDX SEG TABLESPACE_NAME--------------------------- ----------- ------------ ------ --- ------------------------------DOMAIN TABLE VALID VALID YES null--To find the indexes that are causing ORA-29857 , please use the following query :SQL> col TABLE_NAME for a30SQL> col INDEX_NAME for a30SQL> SELECT INDEX_NAME,I.TABLE_NAME FROM DBA_INDEXES I, DBA_TABLES T WHERE T.TABLE_NAME=I.TABLE_NAME AND T.OWNER=I.OWNER AND I.INDEX_TYPE='DOMAIN' and t.TABLESPACE_NAME='SAC';INDEX_NAME TABLE_NAME------------------------------ ------------------------------SAC_INDX SACSQL> DROP INDEX SAC_INDX;Index dropped.--confirm that no secondary objects associated with domain index still exist:SQL> SELECT SECONDARY_OBJECT_OWNER,SECONDARY_OBJECT_NAME,SECONDARY_OBJDATA_TYPE FROM DBA_SECONDARY_OBJECTS WHERE INDEX_NAME='SAC_INDX';no rows selectedSQL> DROP TABLESPACE SAC INCLUDING CONTENTS AND DATAFILES;Tablespace dropped.
問題2:刪除資料表空間期間遭遇 ORA-02429
對於ORA-02429這個錯誤,MOS文檔的描述也很清楚:
Drop Tablespace Failed with ORA-02429: cannot drop index used for enforcement of unique/primary key (文檔 ID 1918060.1)
現象:
刪除資料表空間失敗,伴隨下面的錯誤:
SQL> DROP TABLESPACE REP_DATA INCLUDING CONTENTS AND DATAFILES;DROP TABLESPACE REP_DATA INCLUDING CONTENTS AND DATAFILES*ERROR at line 1:ORA-00604: error occurred at recursive SQL level 1ORA-02429: cannot drop index used for enforcement of unique/primary key
解決方案:
Find the constraint name for the unique/primary key, disable the constraint and drop the tablespace again.
找到那些惟一/主鍵約束名,禁用這些約束然後再次刪除資料表空間。
Steps:=====1) Execute below query to find the constraint name:執行下面的查詢來找到約束名:SQL> select owner, constraint_name,table_name,index_owner,index_namefrom dba_constraintswhere (index_owner,index_name) in (select owner,index_name from dba_indexeswhere tablespace_name='<tablespace_name>'); 2) Disable the constraint:禁用約束:SQL> ALTER TABLE <table_name> DISABLE CONSTRAINT <constraint_name>; 3) Drop the tablespace:刪除資料表空間:SQL> DROP TABLESPACE <tablespace_name> INCLUDING CONTENTS AND DATAFILES;
問題3:資料表空間刪除完畢,主機磁碟空間不釋放
如果等待很長時間都沒有釋放,那麼可參考:
建議的操作方法如下:
1、下載一個lsof軟體裝上,google上可以搜到
2、找到正在用被刪檔案的進程
lsof | grep deleted
3、kill掉相應的進程空間就釋放了
一般這種情況,並不建議重啟資料庫或主機。