9i Flashback 简介
				
		
		
				
				 
		
				
						    不得不说,Flashback是我接触到的Oracle最好的一个特性,简单易用,真是居家旅行的必备良药啊。原本以为只有10g才有这个功能,没想到今天发现9i就有了,所以专门来介绍一下在9i下面的flashback的操作。
				
		
		
				
				 
		
				
						1、原理
				
		
		 
		
				    当数据UPDATE或DELETE时,原来的数据会保存在UNDO表空间中,保存的最少时间是UNDO_RETENTION。实际的保存时间与UNDO表空间的大小和数据更改的繁忙程度相关。UNDO_RETENTION的参数(单位为秒)指定Oracle保存用于FlashBack查询的UNDO映像的时间。一般你可以将这个值设为一整天(864000秒),这样你就能看到前一天全天的映像。当然,你的在线UNDO日志必须足够大,大到足以能保存一整天的UNDO日志数据,对于繁忙的Oracle系统,这个数值可以达到很大。
		
		 
		
				
						2、一些限制
				
		
		 
		
				    * 服务器必须配置成使用自动 undo管理。
    * 在使用FlashBack查询时不能使用DDL或者DML。
    * FlashBack不取消DDL操作,例如DROP命令。 
		
		 
		
				    数据库管理员做一些必要的设置之后,一般用户才能使用Flashback查询功能:
    SQL> ALTER SYSTEM SET UNDO_MANAGEMENT=AUTO 
    SQL> ALTER SYSTEM SET UNDO_RETENTION=86400
    SQL> GRANT EXECUTE ON DBMS_FLASHBACK TO USERNAME;
		
		 
		
				
						3、获得SCN或时间点
				
		
		 
		
				    在FlashBack时,可以尝试多个SCN,获取最佳值。
    如果能得知具体时间,那么可以获得准确的数据闪回。
    SQL> alter session set nls_date_format='YYYY-MM-DD HH24:MI:SS'; 
    SQL> select sysdate from v$database;
		
		 
		
				    可通过以下方法获取SCN,但是不知为什么,两种方法获得的 SCN不一样
    SQL> select dbms_flashback.get_system_change_number scn from dual;
    SQL> select max(ktuxescnw * power(2,32) + ktuxescnb) SCN from x$ktuxe;
		
		 
		
				
						4、启用或禁用flashback查询
				
		
		 
		
				使用系统改变数(SCN)或者真实时间来指定FlashBack的时间点来获取数据映象。
		
		 
		
				方法一:
SQL> select * from [TABLE] as of scn 129292;
SQL> select * from [TABLE] as of timestamp to_timestamp('时间','时间格式');
SQL> select * from [TABLE] as of timestamp to_timestamp('2007-12-18 08:40:00','YYYY-MM-DD HH24:MI:SS');
		
		 
		
				方法二:
启用:
SQL> exec dbms_flashback.enable_at_system_change_number(112112); 
SQL> exec dbms_flashback.enable_at_time('28-AUG-02 11:00:00');
启用后看到的只是闪回的结果,实际上并未恢复数据。且闪回状态下不能做DML操作。可以先恢复到一个临时表中。见示例。
		
		 
		
				禁用:
SQL> exec dbms_flashback.disable();
		
		 
		
				
						5、示例:
				
		
		 
		
				declare
  cursor c1 is
    select * from scott.emp_temp;
  r_c1 scott.e%rowt ype;
begin
  loop
    dbms_flashback.enable_at_system_change_number(49570);
    if c1%isopen = false then
      open c1;
    end if;
    fetch c1
      into r_c1;
    dbms_flashback.disable();
    exit when c1%notfound;
    update scott.emp_temp set sal = r_c1.sal where empno = r_c1.empno;
    commit;
  end loop;
  exec dbms_flashback.disable();
  close c1;
end;
/
		
		 
		
				
				 
		 
		
				转一篇的yangtingkun文章:
====================================================================================================
		
		 
		
		
				
				 
		
				    从9i开始,Oracle提供了闪回(FLASHBACK)功能。即查找当前时间之前的某个时间点系统或表的状态。 
    可以闪回的最大时间和回滚空间有关。如果使用了自动管理回滚表空间,那么UNDO_RETENTION给出了闪回支持的最小时间。也就是说,FLASHBACK最少可以支持UNDO_RETENTION给出的时间,如果系统比较闲,则可以闪回更长的时间。(当然,如果回滚表空间的空间分配不足,当系统处于忙时,有可能重用还没有达到UNDO_RETENTION时间限制的数据的空间) 
    使用闪回的一个前提是表不能进行DDL操作。不但不能对DDL操作进行回闪,而且,也无法闪回到DDL操作以前的数据了。 
		
		
				
				 
		
				    Oracle提供两种方法支持闪回: 
		
		
				
				 
		
				    一种是使用DBMS_FLASHBACK包,这是SESSION级的回闪。执行DBMS_FLASHBACK包的ENABLE_AT_TIME或者ENABLE_AT_SYSTEM_CHANGE_NUMBER过程后,当前session处于闪回状态,此时任何的查询返回的是ENABLE_AT_TIME指定的时间点或ENABLE_AT_SYSTEM_CHANGE_NUMBER指定的SCN的时刻对应的状态。当执行DISABLE过程后,系统恢复到当前状态。 
    这种方法是SESSION级别,此后对任何表的任意的查询语句都返回以前某个时间点的结果。不过缺点是闪回状态下,不支持DML语句。如果用以前的某个时间点的数据恢复当前数据,则必须ENABLE_AT_TIME后,打开一个游标,然后DIABLE闪回状态,然后从游标中读取数据并插入到当前表中。 
		
		
				
				 
		
				    第二种方式是采用AS OF语句,这是语句级的回闪。AS OF后面可以跟TIMESTAMP或SCN。通过在查询表后面直接加AS OF时间点的方式,可以查询到那一时刻的数据。这种方法直观方便,使用于恢复个别表,或对某个表提供基于时间点的访问。 
		
		
				
				 
		
				    下面给出一个例子: 
		
		
				
				 
		
				SQL> alter session set nls_date_format = 'yyyy-mm-dd hh24:mi:ss'; 
		
		
				
				 
		
				会话已更改。 
		
		
				
				 
		
				SQL> create table t (id number, name varchar2(30)); 
		
		
				
				 
		
				表已创建。 
		
		
				
				 
		
				SQL> insert into t values (1, 'yangtingkun'); 
		
		
				
				 
		
				已创建 1 行。 
		
		
				
				 
		
				SQL> commit; 
		
		
				
				 
		
				提交完成。 
		
		
				
				 
		
				SQL> select sysdate from dual; 
		
		
				
				 
		
				SYSDATE
-------------------
2005-01-24 23:21:23 
		
		
				
				 
		
				SQL> commit; 
		
		
				
				 
		
				提交完成。 
		
		
				
				 
		
				SQL> select sysdate from dual; 
		
		
				
				 
		
				SYSDATE
-------------------
2005-01-24 23:26:05 
		
		
				
				 
		
				SQL> delete t; 
		
		
				
				 
		
				已删除 1 行。 
		
		
				
				 
		
				SQL> commit; 
		
		
				
				 
		
				提交完成。 
		
		
				
				 
		
				SQL> exec dbms_flashback.enable_at_time(to_timestamp('2005-1-24 23:26:5', 'yyyy-mm-dd hh24:mi:ss')) 
		
		
				
				 
		
				PL/SQL 过程已成功完成。 
		
		
				
				 
		
				SQL> select * from t; 
		
		
				
				 
		
				        ID NAME
---------- ------------------------------
         1 yangtingkun 
		
		
				
				 
		
				SQL> exec dbms_flashback.disable 
		
		
				
				 
		
				PL/SQL 过程已成功完成。 
		
		
				
				 
		
				SQL> select * from t; 
		
		
				
				 
		
				未选定行 
		
		
				
				 
		
				SQL> select * from t as of timestamp to_timestamp('2005-1-24 23:26:5', 'yyyy-mm-dd hh24:mi:ss'); 
		
		
				
				 
		
				        ID NAME
---------- ------------------------------
         1 yangtingkun 
		
		
				
				 
		
				
						
						    上面给出了通过两种方法实现回闪查询的方法。在上面的例子中,我在执行insert命令和delete命令直接间隔了5分钟左右,且提交了一些空事务。这样做的原因是由于Oracle把时间点映射到SCN上,大约每5分钟左右映射依次。因此两个操作间隔5分钟,且保证两个操作间SCN发生了变化,从而使Oracle可以将timestamp正确的映射到不同的SCN上。 
				
				
						
						 
				
						    下面给出两种不同方法是如何实现数据恢复的。 
				
				
						
						 
				
						SQL> select * from t; 
				
				
						
						 
				
						未选定行 
				
				
						
						 
				
						SQL> declare
  2   cursor c is select * from t;
  3   v_record c%rowtype;
  4  begin
  5   dbms_flashback.enable_at_time(to_timestamp('2005-1-24 23:26:5', 'yyyy-mm-dd hh24:mi:ss'));
  6   open c;
  7   dbms_flashback.disable;
  8   loop 
  9    fetch c into v_record;
10    exit when c%NOTFOUND;
11    insert into t values (v_record.id, v_record.name);
12   end loop;
13   close c;
14  end;
15  / 
				
				
						
						 
				
						PL/SQL 过程已成功完成。 
				
				
						
						 
				
						SQL> select * from t; 
				
				
						
						 
				
						        ID NAME
---------- ------------------------------
         1 yangtingkun 
				
				
						
						 
				
						SQL> rollback; 
				
				
						
						 
				
						回退已完成。 
				
				
						
						 
				
						SQL> select * from t; 
				
				
						
						 
				
						未选定行 
				
				
						
						 
				
						SQL> insert into t 
  2  select * from t as of timestamp to_timestamp('2005-1-24 23:26:5', 'yyyy-mm-dd hh24:mi:ss'); 
				
				
						
						 
				
						已创建 1 行。 
				
				
						
						 
				
						SQL> select * from t; 
				
				
						
						 
				
						        ID NAME
---------- ------------------------------
         1 yangtingkun