乐趣区

关于oracle:模拟Oracle11g下用Flashback-Data-Archive进行恢复的若干场景

相干概念

Flashback Data Archive 是什么

Flashback data archiveoracle 11g 中引入的一个新个性。Flashback archive是一个新的数据库对象,用于存储一个或多表的历史数据。Flashback archive是一个逻辑对象,概念上相似于表空间。实际上 flashback archive 能够看作是存储一个或多个表的所有事务变动的逻辑空间。
Oracle 11gFlashback Data Archive 个性。将变动数据另外存储到创立的闪回归档区(Flashback Archive)中,以和 undo 区别开来,这样就能够为闪回归档区独自设置存储策略,使之能够闪回到指定工夫之前的旧数据而不影响 undo 策略。并且能够依据须要指定哪些数据库对象须要保留历史变动数据,而不是将数据库中所有对象的变动数据都保留下来,而只是记录了指定表的数据变动。所以,Flashback Data Archive 是针对对象的爱护,是 Flashback Database 的无力补充。

它和 Flashbak 的区别?

Oracle 中的 flashback 包含:flashback version queryflashback transaction queryflashback databaseflashback tableflashback drop等个性。

在这些闪回技术当中,除了 Flashback Database(依赖于闪回日志)之外,其余的闪回技术都是依赖于Undo 撤销数据,都与数据库初始化参数 UNDO_RETENTION 密切相关。

它们是从撤销数据中读取信息来结构旧数据的。这样就有一个限度,就是 undo 中的信息不能被笼罩。而 undo 段是循环应用的,只有事务提交,之前的 undo 信息就可能被笼罩,尽管能够通过 undo_retention等参数来缩短 undo 的存活期,但这个参数会影响所有的事务,设置过大,可能导致 undo tablespace 疾速收缩。

换句话说:个别的数据库内 undo_retention 只设置了 900 秒,如果事务量太大,在产生误操作后 undo 内的事务被其余顶掉或超过 900 秒,那么就无奈通过 flashbak 进行复原。而 Flashback Data Archiveundo无关,是独自创立一个闪回归档区,把表级的历史记录都存到归档区外面,能够随时查看表级对象的历史状况。

模仿用 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');


能够看到,此时的打算走的是 test_table_delete 这张表的全表扫描,先记着,前面有用。

创立一个用来存储闪回归档的表空间

能够应用现有表空间,但 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_MANAGEMENTAUTO 代表为 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将不可能变成了可能。

复原指标:

  1. truncate 后复原到新增 3 条数据之前的 5 条记录

    1. 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 和一些增加、批改字段的操作,具体的测试步骤不写了,大略是这样:

  1. 在原表减少一个字段,不必波及到 dbms_flashback_archive 包的相干操作,间接新增就能够,在主表减少实现后闪回归档空间的对象表主动减少一个列,如图所示:

2. 如果主表中删除一个列,也不须要波及到 dbms_flashback_archive 包的相干操作,间接删除就能够。然而删除后在闪回归档空间的对象表里存在一列记录,如图所示:

3. 要还原删除列后的表,须要先在主表上减少字段后从对应工夫点内复原

  1. 如果不须要在闪回归档空间的对象表里保留曾经删除列的信息,则须要用 dbms_flashback_archive 包进行解除关系,之后删除回归档空间的对象表里的列。
  2. 如果真要强行drop table,那么只能解除表和闪回归档空间的关系,带来的结果是无奈再复原之前的历史记录。
alter table test_delete no flashback archive;

总结

通过 Flashback Data Archive,咱们能够更好的治理表级别的复原,然而应用Flashback Data Archive 也有一些限度。
比方咱们应该布局数据库中哪些表是十分重要的,将它们退出到闪回归档区里。
另外还须要独自为空间进行布局,这须要肯定的存储用来保留你冀望的历史数据。
对于频繁批改的表,可能不太实用。
以上。

退出移动版