在Oracle11G中,当你删除一张表的时候,Oracle并不会立马就把这个表从数据库中移除,而是将该表与其相关的对象,比如建立在该表上的索引等改一个名字然后一起放在回收站当中.这个特性叫做Flashback Drop.Oracle这样做的目的是为了避免误删除,能够让数据在误删除之后,可以被找回来.这个是一个非常人性化的特性.至少,我和我的小伙伴们觉着这个特性是极好的.
什么是回收站
回收站其实就是一个数据字典,这个数据字典中保存了很多已经被删除的表以及其他相关联的各种对象,比如索引,约束,嵌套表等等.这些已经被删除掉的对象仍旧在占用空间,它们仍旧会占用当前的磁盘配额.只有当我们使用了purge语句来进行清除或者是数据库因为表空间的约束等原因主动来清空回收站.
每一个用户都可以查询自己的回收站信息,除非当前的用户具备SYSDBA的权限,否则当前的用户只能够查询自己的回收站信息.可以通过下面的语句来进行查询回收站的信息:
SELECT * FROM RECYCLEBIN;
当你使用删除表空间以及表空间中的内容的时候,这个表空间中的对象是不会保存在回收站当中的,回收站将会清理掉里面的所有对象.甚至仅仅是删除表空间的时候,回收站也都是要被清空的.还有下面的情况:当删除一个用户的时候,该用户下的所有的对象也不会保存在回收站,并且已经存在回收站的信息也会被清除.类似的情况还有删除一个簇的时候,删除一个类型的时候.
下面是一个例子:
Connected to:Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit ProductionWith the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL> CREATE TABLESPACE TEST 2 DATAFILE 'd:\TEST.DBF' size 30M autoextend on next 10M maxsize unlimited EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO 3 /
Tablespace created.
SQL> create user test identified by test default tablespace test temporary tablespace temp;
User created.
SQL> grant all privileges to test;
Grant succeeded.
SQL> connect test/testConnected.SQL> create table foo as select level as value from dual connect by level<=100;
Table created.
SQL> drop table foo;
Table dropped.
SQL> create table foo as select level as value from dual connect by level<=100;
Table created.
SQL> create index foo_index on foo(value);
Index created.
SQL> drop table foo;
Table dropped.
SQL> select object_name,original_name from recyclebin;
OBJECT_NAME ORIGINAL_NAME------------------------------ --------------------------------BIN$986nsfRiR06Fih8zSV9S/g==$0 FOO_INDEXBIN$BXC+oYZPQ02UuTQl5mcpbw==$0 FOOBIN$zRgQq7WcSA6fosez88IG8w==$0 FOO
SQL> connect / as sysdbaConnected.SQL> drop tablespace test;
Tablespace dropped.
SQL> connect test/testConnected.SQL> select object_name,original_name from recyclebin;
no rows selected
SQL>
通过上面的演示,我们可以看到,当我们删除一个表空间的时候,原来表空间中的对象也被回收站清空了.
当一个对象被删除,然后被放在回收站的时候,这些被删除的表以及与其一同删除的对象,都会被给一个系统自动生成的名字.这个事情是非常必要的,因为这种方式是可以用于解决因为多次删除同一个名字的表而导致的命名的冲突.比如:有一个用户删除了一个名字为 T1 的表,然后重新创建了这个表T1,然后又给删掉了.或者是有两个人删除了同名的两个表.系统给被删除的对象的命名规则是这样子的:
BIN$unique_id$version
上述:
1) unique_id是一个二十六个字母的GUID,这个字符串可以让整个回收站的名字在整个数据库中是唯一的.
2) version是一个由数据库来指定的版本号.
你可以在启动参数中利用recyclebin相关的参数来进行回收站的启动和关闭,当回收站开启的时候,删除表的时候,表以及相关的对象就会放到回收站中.当回收站是关闭的时候,这些表就会被直接删除掉了,这个时候你如果误删除了表的时候,就需要找到另外的恢复手段来进行数据的恢复,比如利用备份文件的方式.
回收站的设置默认是开启的.
ALTER SESSION SET RECYCLEBIN=OFF;ALTER SESSION SET RECYCLEBIN=ON;
可以在找到initSID.ora在其中修改相关的recyclebin的值来修改回收站的开关信息.
查看回收站中的对象
Oracle数据库提供了两种视图来查看在回收站中的对象.
1)user_recyclebin 这个视图可以用来查看自己已经drop的对象,它有一个同义词recyclebin,让查询变得更加简单.下面的两条语句是一样的:
SELECT * FROM USER_RECYCLEBIN;SELECT * FROM RECYCLEBIN;
2)dba_recyclebin 这个视图可以提供给具有管理员权限的用户查看回收站中的数据.
SELECT * FROM DBA_RECYCLEBIN WHERE owner='SCOTT';
另外一种方式,你可以通过SQL*PLUS下面的命令来查看回收站中的信息:
SHOW RECYCLEBIN;
除此之外,Oracle还提供了一个非常不错的方式来查询已经在回收站中的数据:
SELECT * FROM "BIN$wFuUFpdPTHmj1LCCWIAJMA==$0";
1)上面应该是双引号,不能是单引号
2)上面应该是表名,type为table才能被查询出数据.
从回收站中清除对象
如果你确定你已经删除的对象已经确实不需要,并且需要释放其占用的空间的时候,你可以使用PURGE关键字来删除回收站中的信息,当然,前提是你的角色需要具备删除对象的权限.
你可以通过下面的查询语句从回收站中查看所有对象,并且可以查询该已经被删除的表中的数据,然后找到确定的表进行删除操作:
ChenZw> select object_name,original_name,type from recyclebin;
OBJECT_NAME ORIGINAL_NAME TYPE------------------------------ -------------------------------- -------------------------BIN$mCyic562TjebGEtVSB7JwA==$0 FOO TABLEBIN$GKo5uAbmRSqZlMofs4Wx+A==$0 FOO TABLE
已选择2行。
ChenZw> select * from "BIN$GKo5uAbmRSqZlMofs4Wx+A==$0" where rownum<=2;
VALUE---------- 33316 87980
已选择2行。
ChenZw> purge table "BIN$GKo5uAbmRSqZlMofs4Wx+A==$0";
表已清除。
ChenZw> select object_name,original_name,type from recyclebin;
OBJECT_NAME ORIGINAL_NAME TYPE------------------------------ -------------------------------- -------------------------BIN$mCyic562TjebGEtVSB7JwA==$0 FOO TABLE
已选择 1 行。
ChenZw> purge table foo;
表已清除。
除了上面的两种方式之外,还可以使用其他方式来清空当前的回收站中的对象,比如:
PURGE TABLESPACE example;PURGE TABLESPACE example USER oe;
用户也可以通过使用PURGE RECYCLEBIN命令来删除当前用户下的所有的回收站中的对象。
从回收站中恢复对象
使用FLASHBACK TABLE ... TO BEFORE BEFORE DROP [RENAME TO ...]语句从回收站中恢复数据.后面的rename to是可选的,使用这个可选项可以将恢复的表进行重命名.
下面是一个例子:
SQL> drop table foo;
Table dropped.
SQL> select object_name,original_name,type from recyclebin;
OBJECT_NAME ORIGINAL_NAME TYPE------------------------------ -------------------- -------------------------BIN$Cn9JxNU8TzKp2HViGiUF+A==$4 BIN$YDga921kR2eloMbv INDEX BO/FTA==$3
BIN$IOUy08o7QkmhQRUXp98VWg==$0 FOO TABLE
SQL> flashback table foo to before drop;
Flashback complete.
SQL> select count(1) from foo;
COUNT(1)---------- 100
SQL> select object_name,original_name,type from recyclebin;
no rows selected
SQL> drop table foo;
Table dropped.
SQL> select object_name,original_name,type from recyclebin;
OBJECT_NAME ORIGINAL_NAME TYPE------------------------------ -------------------- -------------------------BIN$SEokzU4/TTGzrqYAI1U8CA==$5 BIN$Cn9JxNU8TzKp2HVi INDEX GiUF+A==$4
BIN$lHpRFqtkSYmth5kPQUHxtw==$0 FOO TABLE
SQL> flashback table foo to before drop rename to foobak;
Flashback complete.
SQL> select count(1) from foo;select count(1) from foo *ERROR at line 1:ORA-00942: table or view does not exist
SQL> select count(1) from foobak;
COUNT(1)---------- 100
SQL>
系统提供的自动生成的GUID是一个避免删除表重名的一种非常好的方式,例如下面的例子,我们连续删除了三个名字为foo的表,我们可以使用其中的object_name进行指定的恢复.
SQL> select object_name,original_name,type from recyclebin;
OBJECT_NAME ORIGINAL_NAME TYPE------------------------------ -------------------- -------------------------BIN$BSZ/y+VqSZunPgWVSzjXmQ==$0 FOO TABLEBIN$vVUFoa2nSYmNFgdJoce95g==$7 BIN$yYC/5QdqRFu5MY90 INDEX 4yVI+w==$6
BIN$v+IfzkDyQNa4MbUP+zFPQw==$0 FOO TABLEBIN$lg5YQjdJQGmz57Dj5NQWIw==$0 FOO TABLE
SQL> flashback table "BIN$v+IfzkDyQNa4MbUP+zFPQw==$0" to before drop rename to fooback;
Flashback complete.
SQL> select count(1) from fooback;
COUNT(1)---------- 100
SQL>
作者 陈字文(热衷于PM\ORACLE\JAVA等,欢迎同行交流)EMAIL:ziwen@163.com QQ:409020100
我们恢复了里面的表之后,这个表相关联的数据也就会被恢复,但是恢复之后的INDEX等数据仍旧是ORACLE生成的索引的名字.所以我们需要自己来修改里面的索引的名字
SQL> select index_name from user_indexes where table_name = upper('fooback');
INDEX_NAME------------------------------BIN$vVUFoa2nSYmNFgdJoce95g==$7
SQL> alter index "BIN$vVUFoa2nSYmNFgdJoce95g==$7" rename to fooback_index;
Index altered.