虽然10g及以上版本的Oracle数据库,提供了recyclebin(回收站)功能,可以找回被drop的表。但是仍然存在着很多8i、9i的库以及没有开启recyclebin功能、drop时直接purge操作等,这样的情况下,如果想找回被意外drop的表,常规的手段是通过备份来恢复。如果没有备份,那就没有办法来恢复了。不过ODU提供了一个可能,在没有备份的情况下,恢复被drop表的数据。
下面通过一个示例来演示如何使用ODU来恢复被drop的表。
首先创建一个测试表:
SQL> create table odu_test ( a number,b varchar2(10),c nvarchar2(30),d varchar2(20),e date,f timestamp,g binary_float,h binary_double);
Table created.
SQL> insert into odu_test select rownum,lpad('x',10),'NC测试' || rownum, 'ZHS测试'|| rownum,sysdate+dbms_random.value(0,100),systimestamp+dbms_random.value(0,100),rownum+dbms_random.value(0,10000),rownum+dbms_random.value(0,10000) from dba_objects where rownum<=10000;
10000 rows created.
SQL> commit;
Commit complete.
SQL> create table t1 as select * from odu_test;
Table created.
SQL> drop table odu_test purge;
Table dropped.
在发现重要的表被意外drop掉的时候,应该立即停止应用,offline那个表所在的表空间或关闭数据库。这里odu_test表是建在users表空间下,先将users表空间offline:
SQL> alter tablespace users offline;
Tablespace altered.
然后需要使用logminer来查找被drop表的data object id:
SQL> select group#,status from v$log;
GROUP# STATUS
---------- ----------------
1 INACTIVE
2 INACTIVE
3 CURRENT
SQL> col member for a50
SQL> select member from v$logfile where group#=3;
MEMBER
--------------------------------------------------
/u01/app/oracle/oradata/xty/redo03.log
SQL> exec sys.dbms_logmnr.add_logfile(logfilename=>'/u01/app/oracle/oradata/xty/redo03.log');
PL/SQL procedure successfully completed.
SQL> exec sys.dbms_logmnr.start_logmnr(options=>sys.dbms_logmnr.dict_from_online_catalog);
PL/SQL procedure successfully completed.
SQL> select scn,timestamp,sql_redo from v$logmnr_contents where operation='DDL' and sql_redo like '%odu_test%' order by 2 ;
SCN TIMESTAMP SQL_REDO
---------- ------------------- ----------------------------------------------------------------------
681455 2009-05-08 11:20:50 create table odu_test ( a number,b varchar2(10),c nvarchar2(30),d varc
har2(20),e date,f timestamp,g binary_float,h binary_double);
681521 2009-05-08 11:21:17 create table t1 as select * from odu_test;
681567 2009-05-08 11:21:34 drop table odu_test purge;
SQL> select scn,timestamp,sql_redo from v$logmnr_contents where timestamp=to_date('2009-05-08 11:21:34','yyyy-mm-dd hh24:mi:ss') order by 1;
SCN SQL_REDO
---------- ----------------------------------------------------------------------
681566 set transaction read write;
681567 drop table odu_test purge;
681569 Unsupported
681570 Unsupported
681570
681570
681570
681570 Unsupported
681570
681570
681570
681570 Unsupported
681570
681570
681570
681570 Unsupported
681570
681570
681570
681570
681570
681570
681570 Unsupported
681570 Unsupported
681570
681570
681570
681570 Unsupported
681570
681570
681570
681570 Unsupported
681570
681570
681570
681571 Unsupported
681572
681572 delete from "SYS"."OBJ$" where "OBJ#" = '52230' and "DATAOBJ#" = '5223
0' and "OWNER#" = '57' and "NAME" = 'ODU_TEST' and "NAMESPACE" = '1' a
nd "SUBNAME" IS NULL and "TYPE#" = '2' and "CTIME" = TO_DATE('2009-05-
08 11:20:46', 'yyyy-mm-dd hh24:mi:ss') and "MTIME" = TO_DATE('2009-05-
08 11:20:46', 'yyyy-mm-dd hh24:mi:ss') and "STIME" = TO_DATE('2009-05-
08 11:20:46', 'yyyy-mm-dd hh24:mi:ss') and "STATUS" = '1' and "REMOTEO
WNER" IS NULL and "LINKNAME" IS NULL and "FLAGS" = '0' and "OID$" IS N
ULL and "SPARE1" = '6' and "SPARE2" = '1' and "SPARE3" IS NULL and "SP
ARE4" IS NULL and "SPARE5" IS NULL and "SPARE6" IS NULL and ROWID = 'A
AAAASAABAAAMzdAAS';
681572
681573 commit;
681574 set transaction read write;
681574 Unsupported
681576 commit;
681577 set transaction read write;
681579 Unsupported
681581 commit;
SQL> exec sys.dbms_logmnr.end_logmnr;
PL/SQL procedure successfully completed.
从SCN为681572的几行中,delete from ”SYS”.”OBJ$” where ”OBJ#” = ’52230′ and ”DATAOBJ#” = ’52230′ 可以看到被drop表的data object id为52230。
下面我们使用ODU来恢复这个被删除的表:
Read the rest of this entry
manual, ODU