我們知道,Oracle 10g引入了recyclebin的概念,當我們刪除一個表的時候,若不指定purge,系統只是將這個表重新命名為BIN$開頭的名稱,並在資料字典中修改相關的資料。
Administrator's Guide中是這麼描述recyclebin的:recycle bin實際上是一個包含了刪除的對象的相關資訊的資料字典表。被刪除的表以及相關的對象(比如索引、約束、巢狀表格等等)並沒有被移除,並且依然佔用著空間。它們會繼續使用使用者的空間配額,直到明確將它們從資源回收筒中清除,或者是另一種很少見的情況:由於資料表空間的空間限制,資料庫必須將它們清除。
由此我們可以知道,在Oracle 10g以後,若啟用了recyclebin功能,當你drop一個表的時候,它會仍然佔用著原來的空間。
我們可以使用user_recyclebin或dba_recyclebin來查看資源回收筒中的對象資訊,或者使用recyclebin,它是user_recyclebin的公用同義字。
文檔中提到了,除了手動purge,這些資源回收筒中的對象只有在資料表空間出現空間不足情況時才會被清除。我們可以做個測試(測試環境為RAC10.2.0.1+ASM)
建立一個資料表空間,給它20m的容量
SQL> create tablespace test1 datafile size 20m;Tablespace created.
然後我們在這個資料表空間上建立一個測試表a
SQL> create table w1.a tablespace test1 as select * from dba_objects;Table created.SQL> select owner,segment_name,round(bytes/1024/1024,2)||' MB' m from dba_segments where tablespace_name='TEST1';OWNER SEGMENT_NAME M------------ ---------------------------------------------------------------------------------------W1 A 6 MBSQL>
一張表佔用6M空間,我們再建立2張一樣的測試表
SQL> create table w1.b tablespace test1 as select * from dba_objects;Table created.SQL> create table w1.c tablespace test1 as select * from dba_objects;Table created.SQL> select round(sum(bytes)/1024/1024,2)||' MB' from dba_segments where tablespace_name='TEST1';ROUND(SUM(BYTES)/1024/1024,2)||'MB'-------------------------------------------18 MB
此時資料表空間已經使用了18M。這時我們把這三張表都刪除
SQL> drop table w1.a;Table dropped.SQL> drop table w1.b;Table dropped.SQL> drop table w1.c;Table dropped.SQL> select owner,object_name,original_name from dba_recyclebin where ts_name='TEST1';OWNER OBJECT_NAME------------------------------ ------------------------------ORIGINAL_NAME--------------------------------W1 BIN$r6HZooW/xpzgQKjAb01Spw==$0BW1 BIN$r6HZooW+xpzgQKjAb01Spw==$0AW1 BIN$r6HZooXAxpzgQKjAb01Spw==$0CSQL> col owner format a4SQL> col segment_name format a35SQL> col m format a10SQL> select owner,segment_name,round(bytes/1024/1024,2)||' MB' m from dba_segments where tablespace_name='TEST1';OWNE SEGMENT_NAME M---- ----------------------------------- ----------W1 BIN$r6HZooXAxpzgQKjAb01Spw==$0 6 MBW1 BIN$r6HZooW+xpzgQKjAb01Spw==$0 6 MBW1 BIN$r6HZooW/xpzgQKjAb01Spw==$0 6 MBSQL>
可以看到,3張表到了資源回收筒中,空間也沒有釋放。
此時20m的資料表空間還剩餘2m可用,如果我再建立一張同樣的表呢
SQL> alter session set tracefile_identifier='rctest';Session altered.SQL> alter session set sql_trace=true;Session altered.SQL> create table w1.d tablespace test1 as select * from dba_objects;Table created.SQL> alter session set sql_trace=false;Session altered.SQL> select owner,object_name,original_name from dba_recyclebin where ts_name='TEST1';OWNE OBJECT_NAME ORIGINAL_NAME---- ------------------------------ --------------------------------W1 BIN$r6HZooW/xpzgQKjAb01Spw==$0 BW1 BIN$r6HZooXAxpzgQKjAb01Spw==$0 C
可以看到,A表被幹掉了。我們看看從trace檔案裡能找到些什麼
執行create table前,系統先查詢test1資料表空間是否online。執行create table時,先檢查相同的命名空間中是否已經存在相同的名稱。接下來開始更新相關的資料字典,準備插入資料。此時發現空間不夠,怎麼辦?注意下面的資訊:
select obj#, type#, flags, related, bo, purgeobj, con#
from
RecycleBin$ where ts#=:1 and to_number(bitand(flags, 16)) = 16 order
by dropscn
注意這個排序:order by dropscn
接下來Oracle做了什麼呢:
drop table "W1"."BIN$r6HZooW+xpzgQKjAb01Spw==$0" purge
刪除了這個表以後,更新相關的資料字典,並插入新的資料
我們可以得出這樣的結論:當刪除表的時候,若不指定purge,會將表放入到資源回收筒中。在建立新的段時,若資料表空間中沒有足夠的剩餘空間,Oracle會按dropscn順序從資源回收筒中刪除一些對象。如果資料檔案指定了autoextend,那麼這個優先順序次序是:先刪除資源回收筒中的對象,再擴充資料檔案
在刪除使用者的時候,系統首先從資源回收筒中purge相關的表,然後對使用者下的表採用如下的刪除命令
drop table "W1"."D" cascade constraints purge force
然後釋放掉所佔用的空間