比如,创建一张带数据的新表EMP:
SQL> create table emp tablespace users as select * from hr.employees;
Table created.
删除EMP:
SQL> drop table emp;
Table dropped.
救回EMP:
SQL> flashback table emp to before drop;
Flashback complete.
SQL> select count(*) from emp;
COUNT(*)
----------
107
该功能的工作原理是:当“drop table”命令执行时,表及其索引并没有被真正删除,其所占空间(称为段)只是分配给了另一种数据库对象:回收站对象,并且这种所谓的分配使数据和数据块没有发生任何移动,还是待在原来的数据文件及表空间中。
回收站对象的信息可以通过查询dba_recyclebin视图(所有回收站对象)获得,普通用户可以使用快捷方式“show recyclebin”命令查看自己的回收站:
SQL> show recyclebin
ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME
--------------- ----------------------------- ------------ -------------------
EMP BIN$r4C+sgsryyQAsLSrtbv==$0 TABLE 2018-10-15:29:57:41
回收站对象本身也可以被查询:
SQL> select count(*) from "BIN$r4C+sgsryyQAsLSrtbv==$0";
COUNT(*)
----------
109
将回收站对象取出,并命名一个新名字:
SQL> flashback table emp to before drop rename to empold;
Flashback complete.
如果表名重复,在闪回时遵循后入先出原则,留意“show recyclebin”命令显示的“DROP TIME”字段:
SQL> show recyclebin
ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME
---------------- ----------------------------- ----------- -------------------
EMP BIN$r4C+sgsryyQAsLSrtbv==$0 TABLE 2018-12-18:53:05:59
EMP BIN$r4C+sgsryyQAsLSrtbv==$0 TABLE 2018-12-18:53:05:35
或者在闪回时指明被恢复的回收站对象:
SQL> flashback table "BIN$r4D3SgQXjj7gQAsLDAsxdw==$0" to before drop;
Flashback complete.
回收站对象毕竟是一种弱存在,Oracle没有义务永远保留被删除的表的数据,表空间在自动增长的压力下会按照先入先出的规则将回收站对象的区(数据块的集合)分配给需要空间的段,在将回收站对象耗尽之前数据文件是不会自动增长的,反之,若数据文件自动增长了,那么在其内的所有回收站对象已经全部失效了。
以下查询可以确认有哪些回收站对象因为原本属于自身的区(数据块的集合)被别的段占用已经不能回到被DROP之前了:
SQL> select owner,object_name,original_name
2 from dba_recyclebin where can_undrop='NO';
no rows selected
若无意使用回收站服务,可以采用purge命令或子句清空或跳过回收站。比如,删除EMP表并且不产生回收站对象:
SQL> drop table emp purge;
Table dropped.
删除一个特定的回收站对象:
SQL> purge table "BIN$r4D3SgQmjj7gQAsLDAsxdw==$0";
Table purged.
删除当前用户的回收站中的所有对象:
SQL> purge user_recyclebin;
Recyclebin purged.
删除USERS表空间中的所有的回收站对象:
SQL> purge tablespace users;
Tablespace purged.
删除数据库中所有的回收站中的所有对象:
SQL> purge dba_recyclebin;
DBA Recyclebin purged.
若要完全禁用回收站功能,可将静态参数recyclebin改为“off”后重启实例:
SQL> alter system set recyclebin='off' scope=spfile;
System altered.
SQL> startup force;
ORACLE instance started.