电脑故障

位置:IT落伍者 >> 电脑故障 >> 浏览文章

闪回查询(Flashback Query)


发布日期:2022/5/19
 

作者gototop

简介

在过去如果用户误删/更新了数据后作为用户并没有什么直接的方法来进行恢复他们必须求助DBA来对数据库进行恢复到了Oraclei这一个难堪局面有所改善Oracle i中提供了一项新的技术手段闪回查询用户使用闪回查询可以及时取得误操作前的数据并可以针对错误进行相应的恢复措施而这一切都无需DBA干预

下面我们通过一个例子来具体说明闪回查询的用法

示例

使用闪回查询前必须确定下面两个参数

UNDO_MANAGEMENT = AUTO

undo_retention = ; #这个时间可以随便设他表示在系统中保留提交了的UNDO信息的时间就是保留分钟

使用闪回查询

SQL> conn sys/sys as sysdba

Connected

SQL> create user flash identified by flash;

User created

SQL> grant connect resource to flash;

Grant succeeded

SQL> grant execute on dbms_flashback to flash;

Grant succeeded

SQL> conn flash/flash

Connected

SQL> set echo on

SQL> create table t (a varchar());

Table created

SQL> insert into t values(gototop);

row created

SQL> insert into t values();

row created

SQL> /

SQL> select * from t;

A

gototop

SQL> set time on

:: SQL>

:: SQL>

:: SQL> delete t where a=gototop;

row deleted

:: SQL> commit;

Commit complete

:: SQL> select * from t;

A

:: SQL> execute DBMS_FLASHBACKENABLE_AT_TIME(to_date( ::));

PL/SQL procedure successfully completed

:: SQL> select * from t;

A

gototop

:: SQL> execute DBMS_FLASHBACKDISABLE;

PL/SQL procedure successfully completed

:: SQL> select * from t;

A

使用闪回查询恢复数据

:: SQL> select * from t;

no rows selected

:: SQL> insert into t values();

row created

:: SQL> /

row created

:: SQL> /

row created

:: SQL> /

row created

:: SQL> /

row created

:: SQL> commit;

Commit complete

:: SQL> /

Commit complete

:: SQL> /

Commit complete

:: SQL> select * from t;

A

rows selected

:: SQL>

:: SQL> delete t;

rows deleted

:: SQL> commit;

Commit complete

:: SQL> commit;

Commit complete

:: SQL> /

Commit complete

:: SQL> declare

:: cursor flash_recover is

:: select * from t;

:: t_recode t%rowtype;

:: begin

:: DBMS_FLASHBACKENABLE_AT_TIME(to_date( ::));

:: open FLASH_RECOVER;

:: DBMS_FLASHBACKDISABLE;

:: loop

:: FETCH FLASH_RECOVER INTO t_recode;

:: EXIT WHEN FLASH_RECOVER%NOTFOUND;

:: insert into t values (t_recodea);

:: end loop;

:: CLOSE FLASH_RECOVER;

:: commit;

:: end;

:: /

PL/SQL procedure successfully completed

:: SQL> :: SQL>

:: SQL> select * from t;

A

:: SQL>

我们可以已经恢复了条纪录但我们要恢复的条纪录为什么会少一条呢?原因就在下面

局限性

闪回查询是基于SCN的虽然我执行的是

DBMS_FLASHBACKENABLE_AT_TIME(to_date( ::));

但Oracle并不会精确的这个时间点而是ROUND DOWN到最近的一次SCN然后从这个SCN开始进行恢复而Oracle i是每五分钟记录一次SCN的并将SCN和对应时间的映射做个纪录

这正是上面我们进行恢复时少了一条的原因因此如果使用DBMS_FLASHBACKENABLE_AT_TIME来进行恢复为了避免恢复失败我可以先等分钟然后再进行恢复

使用DBMS_FLASHBACKENABLE_AT_TIME进行恢复还有一个缺点那就是在Oracle i中SCN和对应时间的映射信息只会保留因此我们无法通过DBMS_FLASHBACKENABLE_AT_TIME来恢复天前的数据如果你想使用闪回查询来恢复天前的数据你必须自己来确定需要恢复的SCN然后使用

DBMS_FLASHBACKENABLE_AT_SYSTEM_CHANGE_NUMBER(SCN_NUMBER); 来定位你的恢复时间点下面是使用方法

:: SQL> VARIABLE SCN_SAVE NUMBER;

:: SQL> EXECUTE :SCN_SAVE := DBMS_FLASHBACKGET_SYSTEM_CHANGE_NUMBER;

PL/SQL procedure successfully completed

:: SQL> print SCN_SAVE;

SCN_SAVE

E+

:: SQL> execute DBMS_FLASHBACKENABLE_AT_SYSTEM_CHANGE_NUMBER(:SCN_SAVE);

PL/SQL procedure successfully completed

另外在使用DBMS_FLASHBACKENABLE_AT_TIME前你必须设定你的NLS_DATE_FORMAT的精确程度Oracle默认的是精确到天如果你不设定像上面的例子你不会得到预期结果

如果你使用sysdate和DBMS_FLASHBACKGET_SYSTEM_CHANGE_NUMBER来获取时间点或者SCN值你必须注意它们取得都是当前的时间点和SCN值

你只能在事务开始时进入闪回查询模式如果之前有DML操作则必须COMMIT

闪回查询无法恢复到表结构改变之前因为闪回查询使用的当前的数据字典

上一篇:使用新的list分割方法提高灵活性

下一篇:pessimistic锁定对optimistic锁定(2)