今天在删除一个表的时候以外发现被删除的表没有进入回收站。
定位导致具体问题的真正原因。
10g删除表没有进入回收站(一):http://yangtingkun.itpub.net/post/468/457565
继续昨天的问题,根据重现问题的过程,怀疑问题可能与以下的一个或多个方法有关:分区表、表空间改名以及导入9i版本的表。
个人认为由于9i没有回收站的功能,因此9i导入的表很可能在某些情况下删除时不放入回收站中;而表空间改名也很可能是导致问题的原因,至于分区表,似乎可能性并不大,这个放到最后进行测试。
首先测试是否是表空间重命名造成的问题,这里仍然可以使用前一篇文章步骤中导出的文件,只需要在目标数据库中添加一个新的表空间,使得导入可以顺利完成。
SQL> CONN YANGTK/YANGTK@YTK102
已连接。
SQL> SELECT * FROM TAB;
TNAME TABTYPE CLUSTERID
------------------------------ ------- ----------
T_LOGMNR TABLE
TEST_LOB TABLE
T2 TABLE
T1 TABLE
T TABLE
SQL> SELECT TABLESPACE_NAME FROM DBA_TABLESPACES;
TABLESPACE_NAME
------------------------------
SYSTEM
UNDOTBS1
SYSAUX
TEMP
USERS
EXAMPLE
YANGTK
LOB_SPACE
已选择8行。
SQL> CREATE TABLESPACE TEST DATAFILE 'E:\ORACLE\ORADATA\YTK102\TEST01.DBF' SIZE 10M;
表空间已创建。
下面执行导入操作:
E:\>imp yangtk/yangtk@ytk102 file=t_partition.dmp tables=t_partition
Import: Release 10.2.0.1.0 - Production on 星期三 3月 19 15:31:06 2008
Copyright (c) 1982, 2005, Oracle. All rights reserved.
连接到: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
经由常规路径由 EXPORT:V09.02.00 创建的导出文件
警告: 这些对象由 TEST 导出, 而不是当前用户
已经完成 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集中的导入
. 正在将 TEST 的对象导入到 YANGTK
. 正在将 TEST 的对象导入到 YANGTK
. . 正在导入分区 "T_PARTITION":"P1"导入了 0 行
. . 正在导入分区 "T_PARTITION":"P2"导入了 0 行
成功终止导入, 没有出现警告。
然后检查这个对象删除后是否进入回收站。
SQL> DROP TABLE T_PARTITION;
表已删除。
SQL> SELECT * FROM TAB;
TNAME TABTYPE CLUSTERID
------------------------------ ------- ----------
T_LOGMNR TABLE
TEST_LOB TABLE
T2 TABLE
T1 TABLE
T TABLE
既然没有执行RENAME TABLESPACE的操作,问题就出现了,说明这个问题应该和RENAME TABLESPACE没有关系,那么下面就可以排查是否和9i版本导入的表有关。
SQL> ALTER USER YANGTK DEFAULT TABLESPACE SYSTEM;
用户已更改。
SQL> CREATE TABLE T_PARTITION (ID NUMBER, NAME VARCHAR2(30))
2 PARTITION BY RANGE (ID)
3 (PARTITION P1 VALUES LESS THAN (100) TABLESPACE TEST,
4 PARTITION P2 VALUES LESS THAN (200) TABLESPACE TEST);
表已创建。
在10g环境下使用同样的脚本建立分区表。下面对这个表进行导出操作:
E:\>exp yangtk/yangtk@ytk102 file=t_partition_10g.dmp tables=t_partition
Export: Release 10.2.0.1.0 - Production on 星期三 3月 19 15:37:13 2008
Copyright (c) 1982, 2005, Oracle. All rights reserved.
连接到: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
已导出 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集
即将导出指定的表通过常规路径...
. . 正在导出表 T_PARTITION
. . 正在导出分区 P1导出了 0 行
. . 正在导出分区 P2导出了 0 行
成功终止导出, 没有出现警告。
删除分区表和对应的表空间:
SQL> DROP TABLE T_PARTITION;
表已删除。
SQL> PURGE TABLE T_PARTITION;
表已清除。
SQL> DROP TABLESPACE TEST INCLUDING CONTENTS AND DATAFILES;
表空间已删除。
现在为了确保10g的导出结果可以导入,仍然采用第一篇文章中提到的修改表空间名称的方法:
SQL> ALTER TABLESPACE YANGTK RENAME TO TEST;
表空间已更改。
执行导入操作:
E:\>imp yangtk/yangtk@ytk102 file=t_partition_10g.dmp tables=t_partition
Import: Release 10.2.0.1.0 - Production on 星期三 3月 19 15:43:28 2008
Copyright (c) 1982, 2005, Oracle. All rights reserved.
连接到: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
经由常规路径由 EXPORT:V10.02.01 创建的导出文件
已经完成 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集中的导入
. 正在将 YANGTK 的对象导入到 YANGTK
. 正在将 YANGTK 的对象导入到 YANGTK
. . 正在导入分区 "T_PARTITION":"P1"导入了 0 行
. . 正在导入分区 "T_PARTITION":"P2"导入了 0 行
成功终止导入, 没有出现警告。
下面恢复表空间的名称,并测试删除操作:
SQL> ALTER TABLESPACE TEST RENAME TO YANGTK;
表空间已更改。
SQL> ALTER USER YANGTK DEFAULT TABLESPACE YANGTK;
用户已更改。
SQL> DESC T_PARTITION
名称 是否为空? 类型
-------------------------------------------------- -------- --------------
ID NUMBER
NAME VARCHAR2(30)
SQL> DROP TABLE T_PARTITION;
表已删除。
SQL> SELECT * FROM TAB;
TNAME TABTYPE CLUSTERID
------------------------------ ------- ----------
T_LOGMNR TABLE
TEST_LOB TABLE
T2 TABLE
T1 TABLE
T TABLE
SQL> PURGE TABLE T_PARTITION;
PURGE TABLE T_PARTITION
*
第 1 行出现错误:
ORA-38307: 对象不在回收站中
居然问题也重现了。如果说通过第一个测试,问题变得逐渐明朗,那么测试的结果使得问题变得扑朔迷离了。
如果说采用10g版本进行导入仍然出现问题,那么说明这个问题似乎和跨数据库版本也没有关系。也就是说问题是由于分区表操作的,但是前面的多次测试已经证明,普通建立一个分区表删除后会进入到回收站中,这里可以假设,导致问题的原因不仅是分区表,还有IMP操作,而跟EXP/IMP的版本没有关系。
除了这种推测外,是否还可以做一种假设,就是RENAME TABLESPACE操作,和数据库跨版本的导入都可以造成这个问题的产生,以至于使用排除法进行推断是不准确的。
当然还有另外一种可能性,问题可能和当前数据库的状态有关,也就是说,这个错误很可能在其他数据库中无法重现。
至于问题到底是什么因素造成的,还需要一系列的测试才能说明,先测试一个最简单的,分区表加导入:
SQL> CREATE TABLE T_PARTITION (ID NUMBER, NAME VARCHAR2(30))
2 PARTITION BY RANGE (ID)
3 (PARTITION P1 VALUES LESS THAN (100) TABLESPACE YANGTK,
4 PARTITION P2 VALUES LESS THAN (200) TABLESPACE YANGTK);
表已创建。
脚本稍做调整,然后建立分区表,并利用10g的exp导出,然后删除该表,并利用10g的imp导入,为了节省篇幅,这里将导出、导入的步骤省略:
SQL> DROP TABLE T_PARTITION;
表已删除。
SQL> PURGE TABLE T_PARTITION;
表已清除。
下面验证删除问题:
SQL> SELECT * FROM TAB;
TNAME TABTYPE CLUSTERID
------------------------------ ------- ----------
T_LOGMNR TABLE
TEST_LOB TABLE
T2 TABLE
T1 TABLE
T TABLE
T_PARTITION TABLE
已选择6行。
SQL> DROP TABLE T_PARTITION;
表已删除。
SQL> SELECT * FROM TAB;
TNAME TABTYPE CLUSTERID
------------------------------ ------- ----------
T_LOGMNR TABLE
TEST_LOB TABLE
T2 TABLE
T1 TABLE
T TABLE
BIN$lXZi01z6RL+pzvELmsdRfQ==$0 TABLE
已选择6行。
SQL> PURGE TABLE T_PARTITION;
表已清除。
这次倒是没有重现问题,看来仅靠导入分区表是无法重现问题的。那么前面第一个推测似乎已经站不住脚了,难道真的是两种方法都可能造成这种问题,这个概率也太小了吧。不妨先检测一下第三种情况,删除一个当前已经存在的表,看是否进入回收站:
SQL> SELECT * FROM TAB;
TNAME TABTYPE CLUSTERID
------------------------------ ------- ----------
T_LOGMNR TABLE
TEST_LOB TABLE
T2 TABLE
T1 TABLE
T TABLE
SQL> DROP TABLE T2;
表已删除。
SQL> PURGE TABLE T2;
表已清除。
其他表似乎也没有问题,尝试修改表空间后手工建表,然后重命名删除:
SQL> ALTER TABLESPACE YANGTK RENAME TO TEST;
表空间已更改。
SQL> CREATE TABLE T_PARTITION (ID NUMBER, NAME VARCHAR2(30))
2 PARTITION BY RANGE (ID)
3 (PARTITION P1 VALUES LESS THAN (100) TABLESPACE TEST,
4 PARTITION P2 VALUES LESS THAN (200) TABLESPACE TEST);
表已创建。
SQL> ALTER TABLESPACE TEST RENAME TO YANGTK;
表空间已更改。
SQL> DROP TABLE T_PARTITION;
表已删除。
SQL> PURGE TABLE T_PARTITION;
表已清除。
目前似乎没有了头绪,仔细观察重现问题的操作,检查有哪些因素是遗漏掉的,结果突然发现了一个重要的共同点,出现这个问题分区表的默认表空间是SYSTEM。当时在9i上建立测试用户的时候没有指定默认的表空间,导致虽然分区表的分区存放在TEST表空间,但是分区表本身的表空间是SYSTEM表空间。前两次的测试都使用的是9i导出的dmp文件,也就是说,表最终的表空间都是SYSTEM,而第三次测试一方面是为了最大限度和前面的测试保持一致,另一方面是由于当前的YANGTK表空间需要修改为TEST,因此也选择了将当前用户的默认表空间暂时置为了SYSTEM表空间下。看来问题已经基本上确定了。
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 USERS 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;
表已清除。
这个测试结果已经足以说明问题了,测试一下SYSAUX表空间是否会出现同样的问题:
SQL> CREATE TABLE T_PARTITION (ID NUMBER, NAME VARCHAR2(30))
2 TABLESPACE SYSAUX 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;
表已清除。
再测试一下是否和分区表有关:
SQL> CREATE TABLE T_PARTITION (ID NUMBER, NAME VARCHAR2(30))
2 TABLESPACE YANGTK;
表已创建。
SQL> DROP TABLE T_PARTITION;
表已删除。
SQL> PURGE TABLE T_PARTITION;
表已清除。
SQL> CREATE TABLE T_PARTITION (ID NUMBER, NAME VARCHAR2(30))
2 TABLESPACE SYSTEM;
表已创建。
SQL> DROP TABLE T_PARTITION;
表已删除。
SQL> PURGE TABLE T_PARTITION;
PURGE TABLE T_PARTITION
*
第 1 行出现错误:
ORA-38307: 对象不在回收站中
问题和分区表也没有关系,现在已经可以确认,是由于SYSTEM表空间的特点导致。
相信这个特性再在Oracle的文档上肯定有描述,果然在SQL REFERENCES文档中查到,如果要对一个表执行FLASHBACK TABLE TO BEFORE DROP要求表所处的表空间必须是LOCAL MANAGEMENT的非SYSTEM表空间。
对文档和新特性不熟悉,导致跑了这么大的圈子,以此为戒。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/4227/viewspace-211703/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/4227/viewspace-211703/