今天在删除一个表的时候以外发现被删除的表没有进入回收站。
将问题引深一点。
10g删除表没有进入回收站(一):http://yangtingkun.itpub.net/post/468/457565
10g删除表没有进入回收站(二):http://yangtingkun.itpub.net/post/468/457648
上一篇已经得出了结论,SYSTEM表空间中的表是不会放到回收站中的,这里将问题引申一下:
SQL> SELECT USERNAME, DEFAULT_TABLESPACE FROM USER_USERS;
USERNAME DEFAULT_TABLESPACE
------------------------------ ------------------------------
YANGTK YANGTK
SQL> CREATE TABLE T AS SELECT * FROM USER_TABLES;
表已创建。
SQL> DROP TABLE T;
表已删除。
SQL> PURGE TABLE T;
表已清除。
SQL> CREATE TABLE T TABLESPACE SYSTEM AS SELECT * FROM USER_TABLES;
表已创建。
SQL> DROP TABLE T;
表已删除。
SQL> PURGE TABLE T;
PURGE TABLE T
*
第 1 行出现错误:
ORA-38307: 对象不在回收站中
这个结果其实就是上一篇文章得出的结论,那么如果是表的索引存放在SYSTEM表空间,删除表的时候,是索引不进入回收站,还是表和索引都不进入回收站呢,或者表和索引全都放入回收站呢:
SQL> CREATE TABLE T AS SELECT * FROM USER_TABLES;
表已创建。
SQL> CREATE INDEX IND_T_NAME ON T(TABLE_NAME);
索引已创建。
SQL> DROP TABLE T;
表已删除。
SQL> SELECT OBJECT_NAME, ORIGINAL_NAME FROM USER_RECYCLEBIN;
OBJECT_NAME ORIGINAL_NAME
------------------------------ --------------------------------
BIN$hXh8Pt7wR26EZFIX00PLlw==$0 IND_T_NAME
BIN$/ixKnWDVQqO4kCp5cobDKg==$0 T
SQL> PURGE TABLE T;
表已清除。
SQL> SELECT OBJECT_NAME, ORIGINAL_NAME FROM USER_RECYCLEBIN;
未选定行
SQL> CREATE TABLE T AS SELECT * FROM USER_TABLES;
表已创建。
SQL> CREATE INDEX IND_T_NAME ON T(TABLE_NAME) TABLESPACE SYSTEM;
索引已创建。
SQL> DROP TABLE T;
表已删除。
SQL> SELECT OBJECT_NAME, ORIGINAL_NAME FROM USER_RECYCLEBIN;
OBJECT_NAME ORIGINAL_NAME
------------------------------ --------------------------------
BIN$ZBVuLlNGRIe7yMzbJ5MuFg==$0 IND_T_NAME
BIN$Nm0Il2RPSKKBJIX8OpYk9Q==$0 T
SQL> FLASHBACK TABLE T TO BEFORE DROP;
闪回完成。
SQL> SELECT INDEX_NAME, TABLESPACE_NAME FROM USER_INDEXES WHERE TABLE_NAME = 'T';
INDEX_NAME TABLESPACE_NAME
------------------------------ ------------------------------
BIN$ZBVuLlNGRIe7yMzbJ5MuFg==$0 SYSTEM
SQL> ALTER INDEX "BIN$ZBVuLlNGRIe7yMzbJ5MuFg==$0" RENAME TO IND_T_NAME;
索引已更改。
SQL> DROP INDEX IND_T_NAME;
索引已删除。
SQL> SELECT OBJECT_NAME, ORIGINAL_NAME FROM USER_RECYCLEBIN;
未选定行
对比普通索引和SYSTEM表空间中的索引,答案已经很清晰了,Oracle在这里仍然只是进行了一个判断,当发现删除对象是SYSTEM表空间的,就不放入回收站中。但是对于这种连带删除并没有加以判断,也就是说删除表的操作会使得SYSTEM表空间中的索引进入回收站,而直接删除索引则不会进入回收站。
再来看一下分区表等包括多个SEGMENT的对象:
SQL> CREATE TABLE T_PARTITION (ID NUMBER, NAME VARCHAR2(30))
2 TABLESPACE SYSTEM PARTITION BY RANGE (ID)
3 (PARTITION P1 VALUES LESS THAN (100) TABLESPACE YANGTK,
4 PARTITION P2 VALUES LESS THAN (200) TABLESPACE YANGTK);
表已创建。
SQL> DROP TABLE T_PARTITION;
表已删除。
SQL> PURGE TABLE T_PARTITION;
PURGE TABLE T_PARTITION
*
第 1 行出现错误:
ORA-38307: 对象不在回收站中
SQL> CREATE TABLE T_PARTITION (ID NUMBER, NAME VARCHAR2(30))
2 TABLESPACE YANGTK PARTITION BY RANGE (ID)
3 (PARTITION P1 VALUES LESS THAN (100) TABLESPACE SYSTEM,
4 PARTITION P2 VALUES LESS THAN (200) TABLESPACE SYSTEM);
表已创建。
SQL> INSERT INTO T_PARTITION SELECT ROWNUM, OBJECT_NAME FROM DBA_OBJECTS
2 WHERE ROWNUM < 200;
已创建199行。
SQL> DROP TABLE T_PARTITION;
表已删除。
SQL> FLASHBACK TABLE T_PARTITION TO BEFORE DROP;
闪回完成。
SQL> SELECT TABLE_NAME, PARTITION_NAME, TABLESPACE_NAME FROM USER_TAB_PARTITIONS;
TABLE_NAME PARTITION_NAME TABLESPACE_NAME
------------------------------ ------------------------------ ---------------
T_PARTITION P1 SYSTEM
T_PARTITION P2 SYSTEM
SQL> SELECT COUNT(*) FROM T_PARTITION;
COUNT(*)
----------
199
从分区表和索引的例子也可以看出,并非SYSTEM表空间中的对象无法进入回收站,而是Oracle在这里进行了判断。出于兼容的考虑,数据字典操作不太可能在DROP的时候添加PURGE语句,个人怀疑是避免数据字典的DROP操作被放入回收站,从而导致系统中对象数量的不断增大,进而影响系统的性能。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/4227/viewspace-214843/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/4227/viewspace-214843/