通過查詢UNDO段來抽取所有已變化的記錄細節,在此基礎之上再構造和執行能夠倒退這些變化的語句
表閃回通過執行倒退變化的語句並且該執行是一個事務,所有常用規則在該事務上起作用。
表閃回時,表上的觸發器缺省被禁用,即該表上的DML觸發器將暫時失效,可以在閃回時指定觸發器是否失效。
表閃回需要啟用表上的記錄轉移選項
--1.下面給出表閃回的種方式
FLASHBACK TABLE <schema_name.table_name>
TO SCN <scn_number> --基於SCN的表閃回
[<ENABLE | DISABLE> TRIGGERS]
FLASHBACK TABLE <schema_name.table_name>
TO TIMESTAMP <timestamp> --基於TIMESTAMP的表閃回
[<ENABLE | DISABLE> TRIGGERS]
FLASHBACK TABLE <schema_name.table_name>
TO RESTORE POINT <restore_point> --基於RESTORE POINT的表閃回
[<ENABLE | DISABLE> TRIGGERS]
--2.演示基於SCN的表閃回
下面的演示首先創建表tb_tables,並對表分幾次插入數據,在完成插入前記錄其SCN號用於後續對其進行閃回
create table tb_emp as --創建演示表tb_emp
select empno,ename,job,deptno from scott.emp where 1=0;
select table_name,row_movement from user_tables; --查看表的row movement行為,缺省為disable
TABLE_NAME ROW_MOVE
------------------------------ --------
TB_EMP DISABLED
select current_scn,systimestamp from v$database; --獲取系統當前的SCN
CURRENT_SCN SYSTIMESTAMP
----------- --------------------------------------
661490 01-JAN-11 10.56.28.733000 PM +08:00
insert into tb_emp --插入deptno為10的員工
select empno,ename,job,deptno from scott.emp where deptno=10;
commit;
select current_scn,systimestamp from v$database; --獲取系統當前的SCN
CURRENT_SCN SYSTIMESTAMP
----------- --------------------------------------
661510 01-JAN-11 10.56.56.546000 PM +08:00
insert into tb_emp --插入deptno為20的員工
select empno,ename,job,deptno from scott.emp where deptno=20;
commit;
select current_scn,systimestamp from v$database; --獲取系統當前的SCN
CURRENT_SCN SYSTIMESTAMP
----------- --------------------------------------
661521 01-JAN-11 10.57.17.358000 PM +08:00
insert into tb_emp --插入deptno為30的員工
select empno,ename,job,deptno from scott.emp where deptno=30;
commit;
select current_scn,systimestamp from v$database; --獲取系統當前的SCN
CURRENT_SCN SYSTIMESTAMP
----------- --------------------------------------
661539 01-JAN-11 10.57.37.843000 PM +08:00
select deptno,count(*) from tb_emp group by deptno order by 1;
DEPTNO COUNT(*)
---------- ----------
10 3
20 5
30 6
flashback table tb_emp to scn 661521; --將表閃回到scn為,即插入部門號為的記錄之前
flashback table tb_emp to scn 661521 --閃回失敗,收到錯誤提示,沒有開啟row movement
*
ERROR at line 1:
ORA-08189: cannot flashback the table because row movement is not enabled
alter table tb_emp enable row movement; --開啟表tb_emp表的row movement 功能
flashback table tb_emp to scn 661521; --再次實施閃回,閃回成功
select deptno,count(*) from tb_emp group by deptno order by 1; --記錄中沒有部門為30的記錄
DEPTNO COUNT(*)
---------- ----------
10 3
20 5
flashback table tb_emp to scn 661510; --將表閃回到scn為,即插入部門號為20的記錄之前
select deptno,count(*) from tb_emp group by deptno order by 1; --記錄中沒有部門為20的記錄
DEPTNO COUNT(*)
---------- ----------
10 3
--3.演示基於TIMESTAMP的表閃回
使用to timestamp進行表閃回,繼續使用上面創建的表來進行閃回
--使用timestamp將表閃回到插入部門號10為之前
flashback table tb_emp to timestamp to_timestamp(‘01-JAN-11 10.56.28.733000‘);
flashback table tb_emp to timestamp to_timestamp(‘01-JAN-11 10.56.28.733000‘) --收到錯誤提示
*
ERROR at line 1:
ORA-01466: unable to read data - table definition has changed --表結構發生改變
flasher@ORCL11G> flashback table tb_emp to scn 661539; --可以將表閃回到插入部門號為30的記錄之後
Flashback complete.
此處演示中收到了錯誤提示,註意對於表閃回,可以多次使用同一類型的閃回方式,
可以往前閃回,一旦往前閃回之後,也可以往後進行閃回。
但交叉閃回則提示表定義發生了變化。閃回失敗。我們可以再次創建一張類似的新表進行基於timestamp進行閃回,
與閃回SCN說不同的是,此處使用了timestamp,此演示在此省略。
--4.演示基於RESTORE POINT的表閃回
基於RESTORE POINT的表閃回首先要創建適當的閃回點,創建閃回點的方式為: CREATE RESTORE POINT point_name;
對於閃回成功之後,無用的閃回點可以及時刪除掉,刪除閃回點的方式為: DROP RESTORE POINT point_name
下面對基於RESTORE POINT 閃回進行演示
drop table tb_emp purge; --刪除先前創建的表tb_emp
create table tb_emp --創建演示表tb_emp
enable row movement
as select empno,ename,job,deptno from scott.emp where 1=0;
create restore point zero; --創建閃回點zero
insert into tb_emp --插入deptno為10的員工
select empno,ename,job,deptno from scott.emp where deptno=10;
commit;
create restore point one; --創建閃回點one
insert into tb_emp --插入deptno為20的員工
select empno,ename,job,deptno from scott.emp where deptno=20;
commit;
create restore point two; --創建閃回點two
insert into tb_emp --插入deptno為30的員工
select empno,ename,job,deptno from scott.emp where deptno=30;
commit;
select deptno,count(*) from tb_emp group by deptno order by 1;
DEPTNO COUNT(*)
---------- ----------
10 3
20 5
30 6
flashback table tb_emp to restore point two; --閃回到閃回點two之前
select deptno,count(*) from tb_emp group by deptno order by 1;
flashback table tb_emp to restore point one; --閃回到閃回點one之前
select deptno,count(*) from tb_emp group by deptno order by 1;
DEPTNO COUNT(*)
---------- ----------
10 3
drop restore point two; --刪除創建的閃回點
drop restore point one;
drop restore point zero;
--5.存在參照關系的表閃回
帳戶flasher中表tb1與表tb2存在外鍵關系,表tb1的deptno 參照了表tb2中的deptno列
帳戶flasher中表tb1與scott.emp具有相同的表結構,表tb2與表scott.dept具有相同的表結構
下面為表tb2新增一個deptno,且為表tb1新增一條記錄
create table tb1 --基於表scott.emp來創建表tb1
enable row movement
as
select * from scott.emp ;
create table tb2 --基於表scott.dept來創建表tb2
enable row movement
as
select * from scott.dept;
alter table tb1 --為表tb1添加主鍵約束
add constraint tb1_empno_pk primary key(empno);
alter table tb2 --為表tb2添加主鍵約束
add constraint tb2_deptno_pk primary key(deptno);
alter table tb1 --為表tb1添加外鍵約束
add constraint tb1_tb2_deptno_fk foreign key(deptno)
references tb2(deptno);
insert into tb2 --為表tb2插入一個新部門
select 50,‘Customer‘,‘Landon‘ from dual;
insert into tb1(empno,ename,job,deptno) --為表tb1插入一個新的雇員
select 8000,‘Robinson‘,‘Clerk‘,50 from dual;
commit;
select current_scn from v$database; --獲得當前的scn
--- 687444
delete from tb1 where empno=8000; --刪除先前新增的部門
delete from tb2 where deptno=50; --刪除先前新增的雇員
commit;
flashback table tb1 to scn 687444; --閃回先前刪除的雇員
/*
ERROR at line 1:
ORA-02091: transaction rolled back --提示事務被回滾,外鍵沒有找到
ORA-02291: integrity constraint (FLASHER.TB1_TB2_DEPTNO_FK) violated - parent key not found */
flashback table tb1,tb2 to scn 687444; --將兩個表同時閃回
select empno,ename,deptno,dname --此時新增的雇員被閃回,部門也被閃回
from tb1
inner join tb2
using(deptno)
where deptno=50;
EMPNO ENAME DEPTNO DNAME
---------- ---------- ---------- --------------
8000 Robinson 50 Customer
--6.表閃回的幾個常見問題
a.當閃回刪除操作之前,如果某個鍵值如主鍵被重用,將導致違反主鍵約束,閃回失敗。
b.若閃回所需要的UNDO信息不存在,將引發ORA-08180:no snapshot found based on specified time(未找到基於指定時間的快照)錯誤
c.如果受閃回影響的記錄被其它用戶鎖定,將引發ORA-00054:resource busy and acquire with NOWAIT specified (資源忙碌)錯誤
d.表定義在閃回期間不能發生變化,否則導致ORA-01466:unable to read data - table definition has changed(表定義已變化)錯誤
e.閃回前未啟用row movement,將收到ORA-08189: cannot flashback the table because row movement is not enabled 錯誤
f.對於存在參照關系的情況,建議將主表等一起實施閃回,否則,將收到ORA-02091: transaction rolled back,ORA-02291錯誤
g.SYS 模式中的表不能使用表閃回技術