相关概念
Flashback Data Archive是什么
Flashback data archive
是oracle 11g
中引入的一个新特性。Flashback archive
是一个新的数据库对象,用于存储一个或多表的历史数据。Flashback archive
是一个逻辑对象,概念上类似于表空间。实际上flashback archive
可以看作是存储一个或多个表的所有事务变化的逻辑空间。Oracle 11g
中 Flashback Data Archive
特性。将变化数据另外存储到创建的闪回归档区(Flashback Archive
)中,以和 undo
区别开来,这样就可以为闪回归档区单独设置存储策略,使之可以闪回到指定时间之前的旧数据而不影响 undo
策略。并且可以根据需要指定哪些数据库对象需要保存历史变化数据,而不是将数据库中所有对象的变化数据都保存下来,而只是记录了指定表的数据变化。所以,Flashback Data Archive
是针对对象的保护,是 Flashback Database
的有力补充。
它和Flashbak的区别?
在Oracle
中的flashback
包括: flashback version query
、flashback transaction query
、flashback database
、flashback table
和flashback drop
等特性。
在这些闪回技术当中,除了Flashback Database
(依赖于闪回日志)之外,其他的闪回技术都是依赖于Undo
撤销数据,都与数据库初始化参数UNDO_RETENTION
密切相关。
它们是从撤销数据中读取信息来构造旧数据的。这样就有一个限制,就是undo
中的信息不能被覆盖。而undo
段是循环使用的,只要事务提交,之前的undo
信息就可能被覆盖,虽然可以通过 undo_retention
等参数来延长undo
的存活期,但这个参数会影响所有的事务,设置过大,可能导致undo tablespace
快速膨胀。
换句话说:一般的数据库内undo_retention
只设置了900
秒,如果事务量太大,在发生误操作后undo
内的事务被其他顶掉或超过900
秒,那么就无法通过flashbak
进行恢复。而Flashback Data Archive
和undo
无关,是单独创建一个闪回归档区,把表级的历史记录都存到归档区里面,可以随时查看表级对象的历史情况。
模拟用Flashback Data Archive恢复
环境准备
数据库版本:Oracle Database 11g Enterprise Edition Release 11.2.0.4.0
是否开启归档:否
是否为RAC:否
建立测试表插入测试数据
建立一个测试表test_table_delete
,插入数据如下图所示
查询time_stamp内的数据和执行计划
select * from test_table_delete as of timestamp to_timestamp('2020-09-17 13:55:09','yyyy-mm-dd hh24:mi:ss');
创建一个用来存储闪回归档的表空间
可以使用现有表空间,但Oracle建议最好使用专用表空间
对表空间的要求:
(1)Flashback data archive只能在ASSM的tablespace上创建
(2)Flashback data archive要求必须使用自动undo管理,即undo_management
参数为auto
create tablespace fa_data datafile '/opt/ora_data/fa_01.dbf' size 1G;
查看我们创建的fa_data
表空间是否符合要求:
select dbt.TABLESPACE_NAME,dbt.SEGMENT_SPACE_MANAGEMENT from dba_tablespaces dbt where dbt.TABLESPACE_NAME = 'FA_DATA';
SEGMENT_SPACE_MANAGEMENT
为AUTO
代表为ASSM
方式段管理的表空间
数据库的undo_management
参数也为AUTO
Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.4.0
Connected as lijian@oraclevm
SQL> show parameter undo
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS1
创建一个闪回归档区
语法:
create flashback archive fa_data tablespace fa_data quota 50M retention 1 year;
qutoa
后面跟的是闪回归档区的大小,retention
后面跟的是要保存多久的历史数据。qutoa
如果不设置,默认自增;当闪回归档区数据超过retiontion
设置的值时Oracle会自动清理。
查看闪回归档、闪回归档和表空间的关系
select * from dba_flashback_archive;
select * from dba_flashback_archive_ts;
把测试表分配到闪回归档区
alter table test_table_delete flashback archive fa_data;
查询DBA_FLASHBACK_ARCHIVE_TABLES视图可以获得已经归档的表
select * from dba_flashback_archive_tables;
模拟delete操作(更新不频繁的表)
因为测试库没有那么大量的事务,所以undo会保留很长时间
这里为了模拟,所以采用的看执行计划的方式来判断是否走了Flashback Data Archive
并且下面所有的操作,都没有用flashbak
操作命令,为的就是区别这两种做法
操作过程:删掉一条数据
恢复目标:恢复到表里之前5条数据的情况
delete from test_table_delete where cityid =1002;
commit;
SQL> select * from test_table_delete;
CITYID CITYNAME
-------------------------------------------------- --------------------------------------------------
1001 吉林
1003 武汉
1004 成都
1005 四川
再来看一下之前SQL的执行计划
发现计划里已经走了DBA_FLASHBACK_ARCHIVE_TABLES
里的表,说明已经调用到闪回归档的信息,现在查询出来的数据就是走的Flashback Data Archive
,不走undo
了
进行恢复
SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
TO_CHAR(SYSDATE,'YYYY-MM-DDHH2
------------------------------
2020-09-17 14:47:09 --获取现在的时间
-- 这里的2020-09-17 14:25:54可以一直往前找,delete后实际表里存在4条数据
-- 我们需要找到一个时间点,里面有5条数据的。
SQL> select * from test_table_delete as of timestamp to_timestamp('2020-09-17 14:25:54','yyyy-mm-dd hh24:mi:ss');
CITYID CITYNAME
-------------------------------------------------- --------------------------------------------------
1002 长春
1001 吉林
1003 武汉
1004 成都
1005 四川
-- 这里我们直接用insert into语句,where条件后跟cityid=1002,因为我们知道删的数据是哪条。
SQL> insert into test_table_delete (select * from test_table_delete as of timestamp to_timestamp('2020-09-17 14:25:54','yyyy-mm-dd hh24:mi:ss') where cityid = 1002);
1 row inserted
SQL> commit;
Commit complete
-- 可以看到,id=1002,cityname=长春的数据被我们恢复回来了。
-- 无论是删除1条还是多条,还是删除后表里又新增数据,只要知道当时删除的条件,都可以找回来。
SQL> select * from test_table_delete;
CITYID CITYNAME
-------------------------------------------------- --------------------------------------------------
1002 长春
1001 吉林
1003 武汉
1004 成都
1005 四川
模拟truncate操作
truncate表操作,用
flashbak
命令是无法进行闪回的
但Flashback Data Archive
将不可能变成了可能。恢复目标:
truncate后恢复到新增3条数据之前的5条记录
- truncate后恢复到8条记录
-- 我又新增了3条数据进去
SQL> select * from test_table_delete;
CITYID CITYNAME
-------------------------------------------------- --------------------------------------------------
1002 长春
1006 甘肃
1007 上海
1008 北京
1001 吉林
1003 武汉
1004 成都
1005 四川
8 rows selected
Commit complete
SQL> truncate table test_table_delete;
Table truncated
SQL> select * from test_table_delete;
CITYID CITYNAME
-------------------------------------------------- --------------------------------------------------
-- 用之前5条记录的时间点来看,是否还能查出来数据
SQL> select * from test_table_delete as of timestamp to_timestamp('2020-09-17 14:25:54','yyyy-mm-dd hh24:mi:ss');
CITYID CITYNAME
-------------------------------------------------- --------------------------------------------------
1002 长春
1005 四川
1003 武汉
1004 成都
1001 吉林
-- 我们可以将这个sql的结果insert到test_table_delete表里来完成truncate后的恢复
SQL> insert into test_table_delete (select * from test_table_delete as of timestamp to_timestamp('2020-09-17 14:25:54','yyyy-mm-dd hh24:mi:ss'));
5 rows inserted
SQL> commit;
Commit complete
-- 5条数据被恢复回来
SQL> select * from test_table_delete;
CITYID CITYNAME
-------------------------------------------------- --------------------------------------------------
1002 长春
1005 四川
1003 武汉
1004 成都
1001 吉林
-- 再执行一遍truncate,这次要恢复8条数据
SQL> truncate table test_table_delete;
Table truncated
-- 找到存在8条记录的时间
SQL> select * from test_table_delete as of timestamp to_timestamp('2020-09-17 15:00:00','yyyy-mm-dd hh24:mi:ss');
CITYID CITYNAME
-------------------------------------------------- --------------------------------------------------
1002 长春
1006 甘肃
1007 上海
1008 北京
1005 四川
1003 武汉
1004 成都
1001 吉林
8 rows selected
-- 用Insert语句进行恢复
SQL> insert into test_table_delete (select * from test_table_delete as of timestamp to_timestamp('2020-09-17 15:00:00','yyyy-mm-dd hh24:mi:ss'));
8 rows inserted
SQL> commit;
Commit complete
SQL> select * from test_table_delete;
CITYID CITYNAME
-------------------------------------------------- --------------------------------------------------
1002 长春
1006 甘肃
1007 上海
1008 北京
1005 四川
1003 武汉
1004 成都
1001 吉林
8 rows selected
SQL>
关于Drop table的操作
对于加入了归档空间的table,进行删除的时候会产生一个报错,强制不让你drop这个表
从另一种角度来说,也是存在一定的安全因素。
如果非要删除,那么需要用dbms_flashback_archive
包来解除关联关系,我们来实验一下。
SQL> drop table test_table_delete;
drop table test_table_delete
ORA-55610: 针对历史记录跟踪表的 DDL 语句无效
SQL> EXEC DBMS_FLASHBACK_ARCHIVE.DISASSOCIATE_FBA('LIJIAN','TEST_TABLE_DELETE');
PL/SQL procedure successfully completed
SQL> drop table test_table_delete;
drop table test_table_delete
ORA-55610: 针对历史记录跟踪表的 DDL 语句无效
SQL> exec dbms_flashback_archive.reassociate_fba('LIJIAN','test_table_delete');
PL/SQL procedure successfully completed
发现执行了dbms_flashback_archive
包来解除关联关系,我们也无法drop table
网上的资料说是Oracle的一个bug,也有资料说是在11.2版本修复的,但是我是11.2.0.4试过了也不行
既然drop不行,那么测试下rename
和一些添加、修改字段的操作,具体的测试步骤不写了,大概是这样:
- 在原表增加一个字段,不用涉及到
dbms_flashback_archive
包的相关操作,直接新增就可以,在主表增加完成后闪回归档空间的对象表自动增加一个列,如图所示:
2.如果主表中删除一个列,也不需要涉及到dbms_flashback_archive
包的相关操作,直接删除就可以。但是删除后在闪回归档空间的对象表里存在一列记录,如图所示:
- 如果不需要在闪回归档空间的对象表里保存已经删除列的信息,则需要用
dbms_flashback_archive
包进行解除关系,之后删除回归档空间的对象表里的列。 - 如果真要强行
drop table
,那么只能解除表和闪回归档空间的关系,带来的后果是无法再恢复之前的历史记录。
alter table test_delete no flashback archive;
总结
通过Flashback Data Archive
,我们可以更好的管理表级别的恢复,但是使用Flashback Data Archive
也有一些限制。
比如我们应该规划数据库中哪些表是非常重要的,将它们加入到闪回归档区里。
另外还需要单独为空间进行规划,这需要一定的存储用来保存你期望的历史数据。
对于频繁修改的表,可能不太适用。
以上。