Flashback Drop能够恢复意外删除的表,它比其他的恢复机制更快,不会丢失最近的事务,当Drop 一张表时,Oracle并不真正删除表和移除表占用的空间,而是把该表重命名,并放到称作Recycle Bin的地方。
Recycle Bin是一个逻辑容器,保存所有删除的表和他们相关联的对象,包括索引(indexes)、约束(constraints)、触发器(triggers)、嵌套表(nested tables)、LOB段(LOB segments)和LOB索引段(LOB index segments)。
1、如何从Recycle Bin中恢复删除的表
SCOTT@orcl>show recycle; ---查看Recycle Bin中的内容
SCOTT@orcl>create table test as select * fromscott.emp; ---创建测试表
Table created.
SCOTT@orcl>select count(*) from test; ---test表中共有14条记录
COUNT(*)
----------
14
SCOTT@orcl>drop table test; ---删除表
Table dropped.
SCOTT@orcl>select count(*) from test; ---查询结果显示表不存在
select count(*) fromtest
*
ERROR at line 1:
ORA-00942: table orview does not exist
SCOTT@orcl>show recycle; ---再次查看Recycle Bin中的内容
ORIGINALNAME RECYCLEBIN NAME OBJECTTYPE DROPTIME
---------------- ------------------------------ ------------ ------------------
TEST BIN$zbs0W4Lxw67gQKjAC39u6g==$0 TABLE 2012-11-05:15:16:20
---可以看到Recyle Bin中有刚才删除的表,"ORIGINAL NAME"是原始表名,"RECYCLEBIN NAME"是系统重命名后的表名,"OBJECT TYPE"是删除的对象类型,"DROP TIME"是删除时间。"RECYCLEBIN NAME"命名的规则是BIN$$globalUID$version,globalUD是数据库生成的26位长度的标识符,v$version是数据库生成的对象版本号。
SCOTT@orcl>select count(*) from"BIN$zbs0W4Lxw67gQKjAC39u6g==$0" where ename ='SMITH';
COUNT(*)
----------
1
---可以用"RECYCLEBIN NAME"作表名查询其中的内容,查询得到的内容和原始的表test中的内容一致。
SCOTT@orcl>flashback table test to before drop; ---执行恢复操作
Flashback complete.
SCOTT@orcl>show recycle; ---Recycle Bin中已经没有刚才删除的test
SCOTT@orcl>select count(*) from test; ---test表和其中的数据已经恢复
COUNT(*)
----------
14
如果同样的表名进行了多次删除那Recycle Bin中的情况又是怎么样的?又改如何恢复呢?还是以刚才创建的test表为例,先droptest表,然后再创建test表,再删除,之后再创建test表,再次删除。
SCOTT@orcl>droptable test;
Table dropped.
SCOTT@orcl>createtable test(id number);
Table created.
SCOTT@orcl>insertinto test values(10);
1 row created.
SCOTT@orcl>commit;
Commit complete.
SCOTT@orcl>droptable test;
Table dropped.
SCOTT@orcl>createtable test(name char(10));
Table created.
SCOTT@orcl>insertinto test values('scott');
1 row created.
SCOTT@orcl>commit;
Commit complete.
SCOTT@orcl>droptable test;
Table dropped.
SCOTT@orcl>showrecyclebin;
ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME
------------------------------ ---------------- ------------ -------------------
TEST BIN$zbs0W4L0w67gQKjAC39u6g==$0 TABLE 2012-11-05:15:35:54
TEST BIN$zbs0W4Lzw67gQKjAC39u6g==$0 TABLE 2012-11-05:15:35:05
TEST BIN$zbs0W4Lyw67gQKjAC39u6g==$0 TABLE 2012-11-05:15:33:46
SCOTT@orcl>selectcount(*) from "BIN$zbs0W4Lyw67gQKjAC39u6g==$0";
COUNT(*)
----------
14
SCOTT@orcl>select* from "BIN$zbs0W4Lzw67gQKjAC39u6g==$0";
ID
----------
10
SCOTT@orcl>flashbacktable test to before drop;
Flashback complete.
SCOTT@orcl>showrecyclebin;
ORIGINALNAME RECYCLEBINNAME OBJECTTYPE DROP TIME
---------------- ------------------------------ ------------ -------------------
TEST BIN$zbs0W4Lzw67gQKjAC39u6g==$0 TABLE 2012-11-05:15:35:05
TEST BIN$zbs0W4Lyw67gQKjAC39u6g==$0 TABLE 2012-11-05:15:33:46
SCOTT@orcl>select* from test;
NAME
----------
scott
从查询结果中可以看到删除的test是以删除的时间从早到晚排列的,如果Recycle bin中相同"ORIGINALNAME"的对象有多个的话,执行flashback table则恢复最后删除的对象。如果我们想恢复指定的删除对象可以使用"RECYCLEBINNAME"进行恢复,比如我们想恢复"DROPTIME"是"2012-11-05:15:33:46"的对象,可以执行flashbacktable "BIN$zbs0W4Lyw67gQKjAC39u6g==$0" to before drop命令,例如:
SCOTT@orcl>showrecyclebin;
ORIGINALNAME RECYCLEBIN NAME OBJECTTYPE DROP TIME
---------------- ------------------------------ ------------ -------------------
TEST BIN$zbs0W4L1w67gQKjAC39u6g==$0 TABLE 2012-11-05:16:12:28
TEST BIN$zbs0W4Lzw67gQKjAC39u6g==$0 TABLE 2012-11-05:15:35:05
TEST BIN$zbs0W4Lyw67gQKjAC39u6g==$0 TABLE 2012-11-05:15:33:46
SCOTT@orcl>flashbacktable "BIN$zbs0W4Lyw67gQKjAC39u6g==$0" to before drop;
Flashback complete.
SCOTT@orcl>showrecyclebin;
ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME
---------------- ------------------------------ ------------ -------------------
TEST BIN$zbs0W4L1w67gQKjAC39u6g==$0 TABLE 2012-11-05:16:12:28
TEST BIN$zbs0W4Lzw67gQKjAC39u6g==$0 TABLE 2012-11-05:15:35:05
SCOTT@orcl>selectcount(*) from test;
COUNT(*)
----------
14
如果想恢复的表已经存在,我们可以在恢复的时候重命名表,例如:
SCOTT@orcl>flashbacktable test to before drop;
flashback table testto before drop
*
ERROR at line 1:
ORA-38312: originalname is used by an existing object
SCOTT@orcl>flashback table test to before drop rename to test_name;
Flashback complete.
一个有用的查询recyclebin里表数据的技巧,如果一张表中的数据改变多次后,删除了该表,我们要查询删除之前某一个时间点的值可以按如下的方式进行:
SCOTT@orcl>create table test as select * from emp; ---创建测试表
Table created.
SCOTT@orcl>select ename,sal from test whereename='SCOTT'; ---查询scott的工资
ENAME SAL
--------------------
SCOTT 6000
SCOTT@orcl>select to_char(sysdate ,'yyyy-mm-ddhh24:mi:ss') current_time from dual; ---查询当前的时间戳
CURRENT_TIME
-------------------
2012-11-05 17:13:28
SCOTT@orcl>update test set sal=0 whereename='SCOTT'; ---更新scott的工资并提交
1 row updated.
SCOTT@orcl>commit;
Commit complete.
SCOTT@orcl>drop table test; ---删除test表
Table dropped.
SCOTT@orcl>show recyclebin; ---查询回收站
ORIGINALNAME RECYCLEBIN NAME OBJECT TYPE DROP TIME
---------------- ------------------------------ ------------ -------------------
TEST BIN$zbzDMUuYMy/gQKjAC39w4w==$0 TABLE 2012-11-05:17:14:07
SCOTT@orcl>select ename,sal from"BIN$zbzDMUuYMy/gQKjAC39w4w==$0" where ename='SCOTT'; --查询删除的test表,scott的工资为更新后的值。
ENAME SAL
---------- ----------
SCOTT 0
SCOTT@orcl>select ename,sal from"BIN$zbzDMUuYMy/gQKjAC39w4w==$0" as of timestampto_timestamp('2012-11-05 17:13:28','yyyy-mm-dd hh24:mi:ss') whereename='SCOTT'; ---通过加入时间戳条件,可以查询更新之前的值。
ENAME SAL
---------- ----------
SCOTT 6000
如果删除的表中有索引,在恢复表的时候,索引也会自动恢复,但是系统会重命名之前的索引,因此如果我们恢复表后,如果表中还有索引,要把索引重命名为删除之前的名字,以下例子做此说明:
SCOTT@orcl>create table test_ix as select * fromscott.emp; ---创建测试表test_ix
Table created.
SCOTT@orcl>create index test_ix_idx ontest_ix(empno); --在test_ix表的empno字段上创建索引test_ix_idx
Index created.
SCOTT@orcl>select index_name,table_name fromuser_indexes where table_name='TEST_IX';
INDEX_NAME TABLE_NAME
------------------------------------------------------------
TEST_IX_IDX TEST_IX
SCOTT@orcl>drop table test_ix; ---删除test_ix表
Table dropped.
SCOTT@orcl>showrecyclebin;
ORIGINALNAME RECYCLEBINNAME OBJECT TYPE DROP TIME
---------------- ------------------------------ ------------ -------------------
TEST_IX BIN$zbs0W4L3w67gQKjAC39u6g==$0 TABLE 2012-11-05:16:27:34
SCOTT@orcl>select index_name,table_name from user_indexes where index_name='TEST_IX_IDX'; ---索引test_ix_idx同时删除
no rows selected
SCOTT@orcl>flashback table test_ix to before drop; ---恢复表test_ix
Flashback complete
SCOTT@orcl>select index_name,table_name from user_indexes where table_name='TEST_IX'; ---索引已经恢复,但是索引名字改变,被命名与"RECYCLEBIN NAME"相同的名字。
INDEX_NAME TABLE_NAME
------------------------------------------------------------
BIN$zbs0W4L2w67gQKjAC39u6g==$0TEST_IX
SCOTT@orcl>alter index"BIN$zbs0W4L2w67gQKjAC39u6g==$0" rename to test_ix_idx; ---重命名索引名为删除之前的名字
Index altered.
SCOTT@orcl>select index_name,table_name fromuser_indexes where table_name='TEST_IX';
INDEX_NAME TABLE_NAME
------------------------------------------------------------
TEST_IX_IDX TEST_IX
2、Recycle Bin的管理
从10g开始系统默认开启Recycle Bin,但是我们也可以设置关闭Recycle Bin。
SYS@orcl>show parameter recyclebin;
NAME TYPE VALUE
------------------------------- -------------
recyclebin string on
SCOTT@orcl>alter session set recyclebin=off; ---在会话中关闭Recycle Bin功能
Session altered.
SYS@orcl>alter system set recyclebin=offscope=both; ---在系统级关闭Recycle Bin功能
System altered.
SYS@orcl>alter system set recyclebin=on scope=both; ---在系统级打开Recycle Bin
System altered.
可以使用purge recyclebin命令清除回收站中的内容:
SYS@orcl>purgerecyclebin;
Recyclebin purged.
---purge recyclebin等价于purge recyclebin,如果sys用户想删除所有用户Recyclebin中的对象,可以执行puregedba_recyclebin。
SYS@orcl>purgedba_recyclebin;
DBA Recyclebinpurged.
SCOTT@orcl>purge table test; ---删除回收站中指定表
Table purged.
SCOTT@orcl>purge index test_ix_idx; ---删除回收站中指定的索引
SYS@orcl>purge tablespace example; --purge指定表空间的对象
SYS@orcl>selectowner,object_name,original_name,ts_name from dba_recyclebin;
OWNER OBJECT_NAME ORIGINAL_NAME TS_NAME
------------ ---------- ----------------- ------------
TOM BIG1 BIN$zb1fkojzlnHgQKjAC39xhg==$0 TOMS
SCOTT TEST BIN$zbzDMUuYMy/gQKjAC39w4w==$0 USERS
SYS@orcl>purgetablespace toms;
Tablespace purged.
SYS@orcl>selectowner,object_name,original_name,ts_name from dba_recyclebin;
OWNER OBJECT_NAME ORIGINAL_NAME TS_NAME
------------ ---------- ----------------- ------------
SCOTT TEST BIN$zbzDMUuYMy/gQKjAC39w4w==$0 USERS
---回收站中属于toms表空间的对象已经全部清除
如果删除表时不想进入回收站可以执行"drop table 表名 purge"
有关回收站的视图有user_recyclebin,dba_recyclebin, show recyclebin等价于查询user_recyclebin视图,但是视图中显示的内容更多。user_recyclebin显示当前用户recyclebin的信息,dba_recyclebin显示所有用户recyclebin的信息,只有具有dba权限的用户才能查看。
3、使用Recycle Bin注意的事项
- 如果drop的表中有外键,使用flashback drop恢复表时,相关的外键是不会恢复的,需要重新创建外键。
- 被恢复的表的管理对象,比如索引、约束名称不会恢复成删除之前的名称,而是系统自动生成的,在恢复完表后要手工将相应的索引、约束改名。位图索引不能被恢复。
- 表必须存在本地管理表空间,不能恢复字典管理表空间里被删除的表。
- 删除表时,依赖该表的物化视图也会被删除,物化视图不会放入Recycle BIn,在恢复完表后要重新创建相关的物化视图。
- system表空间中的表不允许Flashback Drop恢复。
- 通过truncate命令清空表的数据后,是无法查询Flashbak Drop的表数据,请看下面例子:
SCOTT@orcl>create table test as select * from emp;
Table created.
SCOTT@orcl>selectto_char(sysdate ,'yyyy-mm-dd hh24:mi:ss') current_time from dual;
CURRENT_TIME
-------------------
2012-11-05 18:05:02
SCOTT@orcl>truncatetable test;
Table truncated.
SCOTT@orcl>droptable test;
Table dropped.
SCOTT@orcl>showrecyclebin;
ORIGINALNAME RECYCLEBINNAME OBJECT TYPE DROP TIME
---------------- ------------------------------ ------------ -------------------
TEST BIN$zb2fblw4C0HgQKjAC39x0w==$0 TABLE 2012-11-05:18:05:19
SCOTT@orcl>select* from "BIN$zb2fblw4C0HgQKjAC39x0w==$0";
no rows selected
SCOTT@orcl>select* from as of timestamp to_timestamp('2012-11-05 18:05:02','yyyy-mm-ddhh24:mi:ss') "BIN$zb2fblw4C0HgQKjAC39x0w==$0";
select * from as oftimestamp to_timestamp('2012-11-05 18:05:02','yyyy-mm-dd hh24:mi:ss')"BIN$zb2fblw4C0HgQKjAC39x0w==$0"
*
ERROR at line 1:
ORA-00903: invalidtable name
由于drop表时,系统只是给删除的表加上了一个删除标志,并把被删除的表放入到数据字典中,被删除表所占用的空间并未释放。当被删除表所在的表空间有新对象创建时,系统首先会使用空闲空间,如果空间空间不够,系统就会使用那些已被删除表所占用的空间,如果出现这种情况,该表无法使用Flashback Drop恢复。