[Oracle] Flashback闪回机制

Flashback的目的

在有Flashback之前,如果你对数据误操作,并已提交,这时想回退该误操作,将会是很件麻烦的事情。有人可能会说可以用备份恢复到误操作之前,但正确的操作数据也一起没了。唯一可能的办法就是日志挖掘,但日志挖掘非常繁琐,很难定位。
因此,Oracle推出了Flashback技术,主要目的就是为了恢复误操作。

Flashback家族介绍

数据库 级别:Flashback Database
表级别:Flashback Drop和Flashback Table,Flashback Data Archive
记录级别:Flashback Version Query和Flashback Transaction Query

 Flashback家族 Flashback    
Log
 Tablespace
Recycle Bin
 UNDO 作用
 Flashback Database
 Yes      回滚数据库
 Flashback Drop
   Yes    恢复误删除的表
 Flashback Version Query
     Yes  恢复误操作的数据
 Flashback Transaction Query
     Yes  同上
 Flashback Table
     Yes  同上

Flashback 技术发展历程

[Oracle] Flashback闪回机制_第1张图片

Flashback Version/Transaction Query 和 Flashback Table

Flashback Query 和Flashback Table 都是利用undo实现回退功能,当需要闪回到过去某一时刻时,先利用Flashback Query查询,确认闪回的SCN或Timestamp,然后再利用Flashback Table真正实现闪回。

1. 9i 的 Flashback Query
9i的Flashback Query可以查询过去某个时间点对象的状态,测试如下:
系统当前时间为:
alter session set nls_date_format='yyyy-mm-dd:hh24:mi:ss';
select sysdate from dual;

SYSDATE
-------------------
2011-12-16:02:51:16
假设test表里有如下一条数据:
select * from test;

        ID
----------
         1
现在把该数据删除:
delete from test;
commit;
此时test表中已经没有数据了,但我们依然 可以通过Flashback Query查询之前被删除的数据:
select * from test as of timestamp to_timestamp('2011-12-16:02:51:16','yyyy-mm-dd:hh24:mi:ss');

        ID
----------
         1
必要时还可以恢复 数据:
insert into test select * from test as of timestamp to_timestamp('2011-12-16:02:51:16','yyyy-mm-dd:hh24:mi:ss');
commit;

2. Flashback Version Query
10g 新引入的Version Query可以看到过去某个时间段内,数据是如何变化的,也就是数据的演变历史,为此,10g还引入了一个新的伪列ORA_ROWSCN:记录该数据最后一次修改时的SCN。
create table test (id number, name varchar(10));
insert into test values (1,'first');
commit;
update test set name='second' where id=1;
commit;
update test set name='third' where id=1;
commit;
如上所示,我们创建了一个测试表test,插入一条数据,并对该数据进行两次更新,下面看如何用Version Query获得数据的演变历史:
select versions_xid,versions_startscn,versions_endscn,versions_operation,id,name from test versions between scn minvalue and maxvalue where id=1;

VERSIONS_XID     VERSIONS_STARTSCN VERSIONS_ENDSCN VERSIONS_OPERATION           ID NAME
---------------- ----------------- --------------- -------------------- ---------- ----------
12000900D0720000        6629455993                 U                             1 third
0C0018003D720000        6629455988      6629455993 U                             1 second
0D002A00AD6E0000        6629455888      6629455988 I                             1 first
从下往上看,正好对应着我们之前对该数据的操作历史。
我们以第2行为例,在SCN 6629455888和6629455993 这段期间,数据的状态为(1,second),对应的操作为update。

3. Flashback Transaction Query
Transaction Query可以查看事务的演变历史,使用这个功能需要访问flashback_transaction_query视图。
create table test (id number);
开始第一个事务:
insert into test values (1);
update test set id=11 where id=1;
commit;
开始第二个事务:
insert into test values (2);
update test set id=22 where id=2;
commit;
查看flashback_transaction_query视图获得事务的演变历史:
select XID,OPERATION,COMMIT_SCN,UNDO_SQL from flashback_transaction_query where xid in
    (select versions_xid from test versions between scn minvalue and maxvalue);

XID              OPERATION  COMMIT_SCN UNDO_SQL
---------------- ---------- ---------- ------------------------------------------------------------
10000D000C720000 UPDATE     6629456273 update "A105024"."TEST" set "ID" = '2' where ROWID = 'AACsnzAAEAAABSnAAB';

10000D000C720000 INSERT     6629456273 delete from "A105024"."TEST" where ROWID = 'AACsnzAAEAAABSnAAB';

10000D000C720000 BEGIN      6629456273
0C0002002A720000 UPDATE     6629456260 update "A105024"."TEST" set "ID" = '1' where ROWID = 'AACsnzAAEAAABSnAAA';

0C0002002A720000 INSERT     6629456260 delete from "A105024"."TEST" where ROWID = 'AACsnzAAEAAABSnAAA';

0C0002002A720000 BEGIN      6629456260

4. Flashback Table
根据Flashback Query的演变历史,就可以确定需要回退的时间点,然后再利用Flashback Table功能真正实现回退,注意:在真正回退之前,必须启用row movement。

Flashback Drop

Flashback drop是从Oracle 10g开始才有的功能,原理是每个表空间都会有严格回收站的逻辑区域,当drop时,被删除的表及其关联对象不会被物理删除,只是转移到回收站中,给用户提供一个恢复的可能。
[Oracle] Flashback闪回机制_第2张图片
使用Flashback drop需要注意以下几点:
1. 对system表空间无效
2. sqlplus的版本不能低于10g,否则很多命令无法使用
下面做个测试:
SQL> create table test as select * from dba_objects;
SQL> drop table test;
SQL> show recyclebin;
ORIGINAL NAME    RECYCLEBIN NAME                OBJECT TYPE  DROP TIME
---------------- ------------------------------ ------------ -------------------
TEST             BIN$S5L+aNpzQmOScn8VfpJBAA==$0 TABLE        2011-12-15:22:38:30
SQL> create table test as select * from dba_objects where 2=1;
SQL> drop table test;
SQL> show recyclebin;
ORIGINAL NAME    RECYCLEBIN NAME                OBJECT TYPE  DROP TIME
---------------- ------------------------------ ------------ -------------------
TEST             BIN$XHwrz1OaQaSeq/NQIE85hw==$0 TABLE        2011-12-15:22:39:34
TEST             BIN$S5L+aNpzQmOScn8VfpJBAA==$0 TABLE        2011-12-15:22:38:30
此时recyclebin里有两个test表,查看中两个表的数据个数:
SQL> select count(*) from "BIN$XHwrz1OaQaSeq/NQIE85hw==$0";
  COUNT(*)
----------
         0
SQL> select count(*) from "BIN$S5L+aNpzQmOScn8VfpJBAA==$0";
  COUNT(*)
----------
   1000000
下面试着恢复后一张表:
SQL> flashback table "BIN$S5L+aNpzQmOScn8VfpJBAA==$0" to before drop;
Flashback complete.
SQL> select count(*) from test;
  COUNT(*)
----------
   1000000
下面还要恢复前一张表,并重新命名为test2:
SQL> flashback table "BIN$XHwrz1OaQaSeq/NQIE85hw==$0" to before drop rename to test2;
Flashback complete.

SQL> select count(*) from test2;
  COUNT(*)
----------
         0

Flashback Database

1. 配置Flashback Database
1)Flashback 功能默认是关闭的:
SQL> select name,flashback_on from v$database;

NAME      FLASHBACK_ON
--------- ------------------
O01DMS0   NO
2)配置Flash recovery area:
SQL> alter system set db_recovery_file_dest_size=2G scope=both;
SQL> alter system set db_recovery_file_dest='H:\flashback' scope=both;
3)启用Flashback Database 功能:
SQL> shutdown immediate
SQL> startup mount
SQL> alter database flashback on;
SQL> select name,flashback_on from v$database;

NAME      FLASHBACK_ON
--------- ------------------
O01DMS0   YES
4)设置db_flashback_retention_target:
SQL> alter system set db_flashback_retention_target=1440 scope=both;
5)打开数据库
SQL> alter database open;
2. Flashback Database 操作
1)模拟数据丢失:
SQL> create table test as select * from dba_objects;
Table created.

SQL> select count(*) from test;
  COUNT(*)
----------
     10318

SQL> truncate table test;
Table truncated.

SQL> select count(*) from test;
  COUNT(*)
----------
         0

2)确认能恢复 的时间点
能回退的最早时间,取决于保留的Flashback database log的多少,可以从v$flashback_database_log查看:
SQL> select to_char(OLDEST_FLASHBACK_TIME,'yyyy-mm-dd hh24:mi:ss') from v$flashback_database_log;

TO_CHAR(OLDEST_FLAS
-------------------
2011-12-15 02:41:48

3)恢复数据到指定时间点
SQL> shutdown immediate;
SQL> startup mount;
SQL> flashback database to timestamp to_timestamp('2011-12-15 02:43:00','yyyy-mm-dd hh24:mi:ss');

Flashback complete.
恢复成功后,最好先以readonly的方式打开数据库,以确认恢复达到预期,如果没有达到预期,还可以再进行恢复:
SQL> alter database open read only;

Database altered.

SQL> select count(*) from test;
select count(*) from test
                     *
ERROR at line 1:
ORA-00942: table or view does not exist

SQL> shutdown immediate;
SQL> startup mount;
SQL> flashback database to timestamp to_timestamp('2011-12-15 02:49:00','yyyy-mm-dd hh24:mi:ss');

Flashback complete.

SQL> alter database open read only;

Database altered.

SQL> select count(*) from test;

  COUNT(*)
----------
     10318
4)打开数据库
恢复成功后,以resetlog方式打开数据库:
SQL> shutdown immediate;
SQL> startup mount
SQL> alter database open resetlogs;

Flashback Data Archive

Oracle11g则为flashback家族又带来一个新的成员:flashback data archive。

初看起来,flashback data archive和flashback query没有太大的不同,都是通过as of能够查询之前的数据,但是他们的实现机制是不一样的。Flashback query是通过直接从undo中读取信息来构造旧数据,这样就有一个限制,就是undo中的信息不能被覆盖。而undo段是循环使用的,只要事务提交,之前的undo信息就可能被覆盖,虽然可以通过undo_retention等参数来延长undo的存活期,但这个参数会影响所有的事务,设置过大,可能导致undo tablespace快速膨胀。

Falshback data archive特性则通过将变化数据另外存储到创建的flashback archive中,以和undo区别开来,这样就可以通过为flashback archive单独设置存活策略,使得可以闪回到指定时间之前的旧数据而不影响undo策略。并且可以根据需要指定哪些数据库对象需要保存历史变化数据,而不是将数据库中所有对象的变化数据都保存下来,这样可以极大的减少空间需求。

你可能感兴趣的:(oracle,log,flashback,flashback,undo,RecycleBin)