当前位置: 代码迷 >> 综合 >> Flashback Drop
  详细解决方案

Flashback Drop

热度:45   发布时间:2024-01-17 09:40:52.0

        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恢复。


  相关解决方案