ORACLE 11G中闪回相关的新特性:
oracle 9i和10g中具有用于增强DBA和开发人员执行逻辑数据修补的几个和闪回相关的特新。比如9i中支持闪回查询(基于undo数据),oracle 10g中具有闪回数据库,闪回删除,闪回查询(这个分为闪回查询,闪回版本查询,闪回事务查询),闪回表。
而在oracle 11g中,又推出了一个新特性:闪回数据归档。这一特性通过将变化数据另外存储到创建的闪回归档区中,这样就可以为闪回归档区单独设置存储策略,使之可以闪回到指定时间之前不影响undo策略。
一:什么是闪回数据归档?
闪回数据归档是一个新的数据库对象,其中保留一个或多个表的历史数据。并具有自己的数据存储保留和清洗策略。数据库将buffer cache中的原始数据写到undo表空间中作为undo数据,11g中一个新的后台进程叫FBDA将收集和写这些原始数据到闪回数据归档区用于另外创建一份所有表数据的历史。为了启用闪回归档,必须用flashback data archive子句创建一张表或使用alter table语句为存在的表启用归档。有以下一些原则:
1:闪回数据归档和表之间是一对多的关系。
2:在一个数据库中可以使用多个闪回数据归档以满足不同期限的数据保留策略。
3:可以指定一个闪回归档只针对一个表空间。
4:新的后台进程FBDA从buffer cache收集原始数据记录在闪回归档指定表空间里。
5:oracle自动清洗过期的闪回归档数据。
一旦为一张表启用了归档,会为该表创建一个内部历史表,这个历史表将具有原始表的所有列,还有一些时间戳列。这个历史表用于跟踪事务改变。当对要归档的表进行update、delete时,那么在提交之前,内部历史表会有该事务和undo记录。一个insert操作不会在历史表中也插入一条记录。FBDA后台进程在系统设定的时间间隔被唤醒,默认是5分钟。后台进程拷贝被标记的事务的undo数据到历史表。所以当你更新一个表时,历史表中并不是马上就体现更改。如果数据库中产生大量undo数据,那么系统会自动调整FBDA的休眠时间以满足历史表的记录。直到FBDA后台进程完全记录undo数据到历史表,数据库将不会重用被标记为归档的undo记录。一旦FBDA后台进程完全将相应的undo数据写入历史表,undo记录所用的空间才变得可回收。
这里是一个例子,update或delete数据将马上被跟踪,而插入不会马上被跟踪:
SQL> insert into hr.departments
values (300,'New Department',200,1700);
1 row created.
SQL> commit;
Commit complete.
这个记录不会马上在闪回归档历史表中马上体现。
SQL>
SQL> update departments
set department_name='Last Department'
where department_id=300;
1 row updated.
SQL> commit;
SQL> delete from hr.departments where department_id=300;
1 row deleted.
SQL> commit;
Commit complete.
SQL>
SQL> select department_id, department_name, manager_id, location_id
from hr.SYS_FBA_HIST_70308;
DEPT_ID DEPT_NAME MANAGER_ID LOCATION_ID
------- ---------------- ----------- ------------
300 New Department 200 1700
300 Last Department 200 1700
delete和update的记录会马上在历史表中体现出来。
二:创建闪回归档:
必须具有DBA角色或flashback archive administer系统权限,才能够创建闪回归档。
SQL> select * from dba_sys_privs where privilege like '%FLASH%';
GRANTEE PRIVILEGE ADM
------------------ ----------------------------- --------
SYS FLASHBACK ANY TABLE NO
DBA FLASHBACK ANY TABLE YES
DBA FLASHBACK ARCHIVE ADMINISTER YES
比如,给用户HR一个FLASHBACK ARCHIVE ADMINISTER系统权限
SQL> grant flashback archive administer to hr;
Grant succeeded.
通过使用create flashback语句来创建闪回归档。当然必须首先创建相应表空间。可以指定以下属性:
闪回归档名字;
闪回归档是不是缺省归档;
闪回归档主表空间名;
闪回归档主表空间限额;
闪回归档保留策略;
其中两个关键参数是quota和retention。只使用retention例子如下:
SQL> create flashback archive flash1
tablespace flash_tbs1
retention 4 year;
也可以同时使用quota和retention:
SQL> create flashback archive flash1
tablespace flash_tbs1
quota 2000m
retention 4 year;
你必须分配给闪回归档的空间数量取决于闪回事务的数量和闪回保留期。在闪回归档归档使用到限额之前,或者没有使用quota子句的表空间用满之前,oracle会生成一个空间告警。这给你一定的时间清洗老数据或增加限额或增加表空间容量。
也可以通过如下语句删除闪回归档:
SQL> drop flashback archive flash1;
当然,一旦你删除归档,这些归档数据也会“消失”。虽然闪回归档封装的数据事实上还在,因为可能还保留其它归档数据。你不能删除这些跟踪数据,因为这些数据还有审计和安全目的。
三:改变闪回归档:
使用alert flashback命令来改变闪回归档。
SQL> alter flashback archive flash1
set default; # makes flash1 the default archive
SQL> alter flashback archive flash1
add tablespace flash_tbs1 # adds space to the flashback archive
SQL> alter flashback archive flash1
modify tablespace
flash_tbs1 quota 10G; # changes the quota for the archive
SQL> alter flashback archive flash1
modify retention 2 year; # changes the archive retention time
SQL> alter flashback tablespace flash1
add tablespace flash_tbs2;
SQL> alter flashback tablespace flash1
remove tablespace flash_tbs2;
一个闪回归档所管理的所有表均具有相同的保留时间。
虽然闪回归档数据是自动被清洗的,但是你也可以手工进行清洗。
SQL> alter flashback archive flash1
purge all; # purges all archived data
SQL> alter flashback archive flash1
purge before
timestamp (systimestamp – interval '2' day);
# purges data older than 2 days
SQL> alter flashback archive flash1
purge before scn 123456; # purges all data before the
specified scn
四:启用和禁用闪回归档
必须为想要闪回归档的表启用闪回日志。不能基于数据库级别或表空间级别启用闪回归档。必须显式为想要跟踪的每一张表进行闪回归档。
为了使表启用闪回归档日志,必须具有flashback archive object权限。当然DBA角色自动包含这些权限。
缺省情况下,表的闪回日志是关闭的。
可以使用将闪回日志在创建表时指定,如:
SQL> create table test11 (
name varchar2(30),
address varchar2(50))
flashback archive fla4;
也可以如下指定已经存在的表:
SQL> alter table employees
flashback archive fla1;
如果你指定了缺省闪回归档,那么你也可以只使用flashback archive子句,而不指定闪回归档名。这时,表就使用缺省闪回归档作为表的闪回归档区。
可以通过如下查询来查看哪些表使用了闪回归档:
SQL> select * from dba_flashback_archive_tables;
TABLE_NAME OWNER FLASHBACK_ARCH_NAME ARCH_TABLE_NAM
----------- ------ ------------------- -------------------
EMPLOYEES HR FLASH1 SYS_FBA_HIST_70313
这个例子里,SYS_FBA_HIST_70313就是历史表,它属于HR用户。该表不能够直接更新。但是可以使用as of的sql语句来查询数据。
在能够使用闪回归档之前,你必须首先设置缺省闪回归档。如下查询查看缺省闪回归档:
SQL> select flashback_archive_name,status from
dba_flashback_archive;
FLASHBACK_ARCHIVE_NAME STATUS
---------------------- ------
FLASH1 DEFAULT
可以关闭表的闪回归档特性:
SQL> alter table employees
no flashback archive;
五:闪回归档的限制
对于任何使用闪回归档的表,不能使用drop column DDL语句,但是可以使用add column命令。
如果想删除闪回启用的表的一列,唯一的方法是关闭表的闪回归档。
六:监视闪回归档
1:查看那些表是闪回归档表:
SQL> select * from dba_flashback_archive_tables;
TABLE_NAME OWNER FLASHBACK_ARCHIVE ARCHIVE_TABLE_NAME
--------- ------- ------------------ --------------------
EMPLOYEES HR FLASH1 SYS_FBA_HIST_70313
2:查看所有的闪回归档:
SQL> select flashback_archive_name,retention_in_days
from dba_flashback_archive;
FLASHBACK_ARCHIVE_NAME RETENTION_IN_DAYS
----------------------- -----------------
FLASH1 365
3:查看闪回归档表空间信息:
SQL> select flashback_archive_name, tablespace_name, quota_in_mb
from dba_flashback_archive_ts;
FLASHBACK_ARCHIVE _NAME TABLESPACE_NAME QUOTA_IN_MB
------------------------ --------------- -----------
FLASH1 FLASH1 80
举例:
可以使用闪回归档实现很多有用的功能,比如访问历史数据,审计,恢复数据等。
1:创建一个表空间:
create tablespace fla datafile 'D:\APP\FZS\ORADATA\ORCL11\fla.dbf' size 200m;
2:创建默认闪回归档区:
create flashback archive flash1 tablespace fla retention 4 year;
alter flashback archive flash1 set default;
3:使表支持闪回归档:
alter table big_table flashback archive;
4:表共有10万行数据。
5:使用as of 子句来查询历史数据。
> select sysdate from dual;
SYSDATE
-------------------
2012-04-17 11:28:53
> delete from big_table where id>20000;
80000 rows deleted.
> commit;
Commit complete.
注意此提交时需要一段时间。因为这种提交是要将改变写入历史表的。
>
>
> select count(*) from big_table;
COUNT(*)
----------
20000
> select count(*) from big_table as of timestamp to_timestamp('2012-04-17 11:28:53','yyyy-mm-dd hh24:mi:ss');
COUNT(*)
----------
100000
当你知道时间点的时候,as of这种子句查询历史数据非常好,但是当你不知道时间点时,该怎么办呢?
比如,下面语句查询雇员Zlotkey的薪水:
SQL> select salary from hr.employees where
last_name='Zlotkey';
SALARY
------------
10500
现在人力资源部将其薪水更新,上浮5000.但是不小心操作为上浮了50000,
SQL> update hr.employees set salary=salary+50000
where last_name='Zlotkey';
1 row updated.
SQL> commit;
Commit complete.
为了将其值还原为正确的值,hr只是大概记得是一个小时以前进行的工资上浮操作,并不清楚具体的操作时间,那么
将值改为原有值,采用如下方法:
SQL> update hr.employees set salary =
(select salary from hr.employees
as of timestamp (systimestamp - interval '60' minute);
where last_name='Zlotkey')
where last_name='Zlotkey';
1 row updated.
SQL> commit;
Commit complete.
SQL>
关于systimestamp的用法还有如下几种:
systimestamp – interval '60' second #过去六十秒前
systimestamp – interval '7' day #过去7天前
systimestamp – interval '12' month #过去12个月前
产生数据变化报告:
可以使用在闪回数据归档中的历史数据产生一个数据变化报告,使用versions between子句:
SQL> select * from patient_info
versions between timestamp
to_timestamp ('2007-01-01 00:00:00', 'YYYY-MM-DD HH23:MI:SS')
and maxvalue
where name ='ALAPATI';