被刪除的表,其實並非真正的刪除,而是通過修改數據字典的方式將其改名並放入recycle bin中,如果要恢復recycle bin中的對象,藉助flashback table 是最簡單直接的方式。
除此之外,flashback table 也提供類似flashback query中的AS OF TIMESTAMP/SCN的方法,藉助undo表空間中的undo數據,將現有的表恢復到指定時間點或者scn的狀態。
12:57:12 SQL> select * from db1.milktwo;
ID NAME---------- ----------------------
11 kk
3 aa
12:57:26 SQL> create index db1.mkind on db1.milktwo(id);
Index created.
12:58:24 SQL> purge recyclebin;
Recyclebin purged.
12:58:39 SQL> drop table db1.milktwo;
Table dropped.
12:59:01 SQL> desc dba_recyclebin;
Name Null? Type ----------------------------------------------------------------------------------------------
NOT NULL VARCHAR2(30) OBJECT_NAME
NOT NULL VARCHAR2(30) ORIGINAL_NAME
VARCHAR2(32) OPERATION
VARCHAR2(9) TYPE
VARCHAR2(25) TS_NAME
VARCHAR2(30) CREATETIME
VARCHAR2(19) DROPTIME
VARCHAR2(19) DROPSCN
NUMBER PARTITION_NAME
VARCHAR2(32) CAN_UNDROP
VARCHAR2(3) CAN_PURGE
VARCHAR2(3) RELATED
NOT NULL NUMBER BASE_OBJECT
NOT NULL NUMBER PURGE_OBJECT
NOT NULL NUMBER SPACE
NUMBER
12:59:30 SQL> select owner,OBJECT_NAME,ORIGINAL_NAME from dba_recyclebin; //當刪除表的時候,對應的索引也會被放入recycle bin
OWNER OBJECT_NAME ORIGINAL_NAME
------------------------------ ------------------------------ --------------------------------
DB1 BIN$UtbPKaL3CHPgUwtYqMAwog==$0 MKIND
DB1 BIN$UtbPKaL4CHPgUwtYqMAwog==$0 MILKTWO
13:01:45 SQL> flashback table db1.milktwo to before drop; //也可以flashback table db1."BIN$UtbPKaL4CHPgUwtYqMAwog==$0" to before drop;
Flashback complete.
13:02:31 SQL> select * from db1.milktwo;
ID NAME
---------- ----------------------
11 kk
3 aa
13:05:03 SQL> select owner,table_name,index_name,status from dba_indexes where table_name='MILKTWO'; //閃回以後對應的表的索引不會恢復到原來名稱
OWNER TABLE_NAME INDEX_NAME STATUS
------------------------------ ------------------------------ ------------------------------ --------
DB1 MILKTWO BIN$UtbPKaL3CHPgUwtYqMAwog==$0 VALID
13:05:55 SQL> alter index db1."BIN$UtbPKaL3CHPgUwtYqMAwog==$0"rename to mkind; //通過rename重命名
Index altered.
13:06:09 SQL> select owner,table_name,index_name,status from dba_indexes where table_name='MILKTWO';
OWNER TABLE_NAME INDEX_NAME STATUS
------------------------------ ------------------------------ ------------------------------ --------
DB1 MILKTWO MKIND VALID
13:30:32 SQL> flashback table db1.milktwo to before drop rename to milktwo2; //當閃回之前已經有新表創建了,可以rename
Flashback complete.
//當同一名稱的表先後被刪除多次,那麼flashback的時候如果不指定recyclebin中的OBJECT_NAME,那麼flashback的機制是先恢復最後刪除的,詳細驗證過程如下:
13:40:22 SQL> select * from db1.milktwo;
ID NAME
---------- ----------------------
11 kk
3 aa
13:41:07 SQL> drop table db1.milktwo;
Table dropped.
13:41:59 SQL> create table db1.milktwo (id number,name varchar2(22));
Table created.
13:42:15 SQL> insert into db1.milktwo values(33,'kk');
1 row created.
13:42:40 SQL> select * from db1.milktwo;
ID NAME
---------- ----------------------
33 kk
13:42:52 SQL> drop table db1.milktwo;
Table dropped.
13:43:09 SQL> desc dba_recyclebin
Name Null? Type -------------
NOT NULL VARCHAR2(30) OBJECT_NAME
NOT NULL VARCHAR2(30) ORIGINAL_NAME
VARCHAR2(32) OPERATION
VARCHAR2(9) TYPE
VARCHAR2(25) TS_NAME
VARCHAR2(30) CREATETIME
VARCHAR2(19) DROPTIME
VARCHAR2(19) DROPSCN
NUMBER PARTITION_NAME
VARCHAR2(32) CAN_UNDROP
VARCHAR2(3) CAN_PURGE
VARCHAR2(3) RELATED
NOT NULL NUMBER BASE_OBJECT
NOT NULL NUMBER PURGE_OBJECT
NOT NULL NUMBER SPACE
NUMBER
13:43:25 SQL> select OWNER,OBJECT_NAME,ORIGINAL_NAME,DROPTIME from dba_recyclebin where owner='DB1'; //查看recyclebin
OWNER OBJECT_NAME ORIGINAL_NAME DROPTIME
------------------------------ ------------------------------ -------------------------------- -------------------
DB1 BIN$UtbPKaL8CHPgUwtYqMAwog==$0 MILKTWO 2017-06-26:13:41:21
DB1 BIN$UtbPKaL9CHPgUwtYqMAwog==$0 MILKTWO 2017-06-26:13:43:09
13:45:10 SQL> flashback table db1.milktwo to before drop;
Flashback complete.
13:45:48 SQL> select * from db1.milktwo; //恢復了第二次刪的表
ID NAME
---------- ----------------------
33 kk
基於undo的表恢復被恢復的表必須啓用row movement,表的row movement的屬性用來控制是否允許修改列值所造成的記錄移動,默認值是DISABLED
14:06:56 SQL> select row_movement from dba_tables where TABLE_NAME='MILKTWO'; //查看默認情況的row_movement值
ROW_MOVE
--------
DISABLED
14:08:13 SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
3533043
14:08:46 SQL> select * from db1.milktwo;
ID NAME
---------- ----------------------
33 kk
14:09:03 SQL> insert into db1.milktwo values (5,'ll');
1 row created.
14:09:23 SQL> commit;
Commit complete.
14:09:28 SQL> update db1.milktwo set id=31 where name='kk';
1 row updated.
14:11:52 SQL> commit;
Commit complete.
14:11:55 SQL> flashback table db1.milktwo to scn 3533043; //row movement沒有開的情況下,閃回失敗
flashback table db1.milktwo to scn 3533043
*
ERROR at line 1:
ORA-08189: cannot flashback the table because row movement is not enabled
14:12:27 SQL> alter table db1.milktwo enable row movement; //enable row movement
Table altered.
14:13:12 SQL> flashback table db1.milktwo to scn 3533043; //閃回成功
Flashback complete.
//既然基於undo的,那麼就要注意到ddl對flashback table as of timestamp/scn的影響
14:17:23 SQL> select dbms_flashback.get_system_change_number from dual;
GET_SYSTEM_CHANGE_NUMBER
------------------------
3533626
14:13:19 SQL> select * from db1.milktwo;
ID NAME
---------- ----------------------
33 kk
14:18:09 SQL> insert into db1.milktwo values (2,'hh');
1 row created.
14:18:35 SQL> commit;
Commit complete.
14:19:10 SQL> alter table db1.milktwo move; //ddl操作
Table altered.
14:19:51 SQL> select * from db1.milktwo;
ID NAME
---------- ----------------------
33 kk
2 hh
14:20:00 SQL> flashback table db1.milktwo as of scn 3533626; //flashback 失敗
flashback table db1.milktwo as of scn 3533626
*
ERROR at line 1:
ORA-08187: snapshot expression not allowed here
flashback table 基於undo的其他注意事項:
1.flashback table 實際上是dml操作,因此需要注意triggers對其的影響,flashback table to scn在執行的時候自動回disable掉相關的trigger,如果你想在此期間triggers繼續發揮作用,可以在flashback table時附加enabletriggers子句。
2.基於undo的表恢復,索引會自動維護,但是統計信息並不會恢復到指定時間。
3.基於undo表的恢復也有侷限性,不支持以下類型的表:聚簇表,物化視圖,高級對列表,系統表,遠程表,嵌套表及表分區或者子分區。
flashback table 基於recycle bin的其他注意事項:
1.flashback drop不能恢復參照完整性,就是說如果此表有主外鍵約束,那麼恢復之後,該約束的disable的,需要手工處理
2.所操作的表必須存在於本地管理表空間
3.被恢復的表的關聯對象並不會恢復到之前的名稱,可以rename
4.當刪除表的時候,依賴於此表的視圖也會被刪除,但是由於物化視圖並不會放入recyclebin中,那麼flashback的時候並不會恢復。
5.相對於被刪除的表而言,當表空間不足的時候,oracle會先清理被刪除的表索引,再是表,所以恢復出來可能沒有索引
6.flashback drop 支持同時操作多個表,以逗號隔開