FlashBack概述

目的:

  • 误操作恢复:误删除表、误删除数据、其他错误的数据库操作
  • 对之前数据的查询

闪回操作:

  • 闪回查询:闪回查询、闪回版本查询、闪回事务查询
  • 闪回数据:闪回表、闪回删除、闪回数据、闪回归档

闪回查询

查询某个时间点表中的数据(某个时间点表中数据的快照):

  1. select * from t as of timestamp to_timestamp('2021-03-28 2:19:12', 'YYYY-MM-DD hh:mi:ss');

基于SCN查询:

  1. -- 获取当前scn
  2. select current_scn from v$database;
  3. select * from t as of scn 1559881;

闪回版本查询

查询一段时间版本内的事务对数据做的操作:

  1. select
  2. versions_xid,versions_starttime,versions_endtime,versions_operation, -- oracle生成的伪列
  3. t.*
  4. from t
  5. versions between timestamp minvalue and maxvalue;

闪回事务查询

根据事务ID查看改变的数据:

可以查看哪些事务、哪些用户做了哪些操作,并且可以查到撤销这些操作的SQL语句(undo_sql)

  1. select * from flashback_transaction_query;

闪回表

将表闪回到历史的某个时刻:

  1. -- 允许表的行移动:A数据原本rowID为表中第1行,然后A数据被删掉了,插入了B数据,B数据可能占用了表中的第1行。此时闪回表时,就需要用到行移动,将A数据插入到其他的RowID中。(即表中的数据闪回回来了,但是RowID可能和之前不同了)
  2. alter table t enable row movement;
  3. -- 闪回
  4. flashback table t to scn 6955918;

闪回删除和回收站

表被drop之后的闪回:

表的drop是一个DDL操作,DDL不会产生undo。

表的drop操作本身不会产生undo,但是表drop的时候需要修改一些系统字典表,这些改变会产生undo。表drop的时候,表中的数据被清空也没有undo。

oracle中表drop的闪回是使用的回收站。

  1. -- 查看回收站是否开启(默认开启)
  2. show parameter recyclebin;
  3. -- 查看回收站的内容
  4. show recyclebin;
  5. -- 回收站中查看到的表也可以进行查询
  6. select * from "BIN$Kn33CX6ISY1K8Jra/KEig==$0";
  7. -- 表删除之后的闪回
  8. flashback table t to before drop;

清空回收站:

  1. -- 删除表时不加入回收站
  2. drop table t purge;
  3. -- 清空回收站全部内容
  4. purge recyclebin;
  5. -- 只将表t从回收站中清除
  6. purge table t;

表被drop进回收站之后,在数据库中占据的空间并没有释放,只是改了个回收站里的名字继续存在于数据库中,在user_segments中可以查到这个回收站里的对象,甚至还可以通过回收站的名字进行正常查询这张表。但是dba_free_space视图中已经认为这部分空间被释放了,所以dba_free_space视图中的表空间剩余空间会增加。

闪回归档

闪回过程中,可能会有一些报错:

ORA-01466:表闪回的时间段内,执行过DDL操作,表定义改变了。

ORA-08180:指定的闪回时间还没有快照。

ORA-01555:快照过旧,已经被覆盖了。

因为这些不可预知的问题,oracle在11g时开发了闪回归档技术:用实际的数据来记录数的修改,让恢复永不过期。

专有的后台进程fbda 异步的捕获数据,存放到一个特定的表空间中:

  • 默认5分钟
  • 所改变的活跃程度调整

操作:

  1. -- 创建一个表空间,用来存放闪回数据
  2. create tablespace his_data_1
  3. datafile '+data' size 500M;
  4. -- 创建一个默认的闪回归档
  5. create flashback archive
  6. default fba1
  7. tablespace his_data_1
  8. retention 7 day; -- 保留7
  9. -- 创建一个闪回归档
  10. create flashback archive
  11. default fba2
  12. tablespace his_data_1
  13. quota 200M -- 空间配额
  14. retention 30 day;
  15. -- 给用户授权
  16. grant flashback archive on fba1 to scott;
  17. grant flashback archive on fba2 to scott;
  18. -- 创建启用闪回归档的表
  19. create table empsal_his(
  20. empno number,
  21. ename varchar2(10),
  22. sal number,
  23. flashback archive
  24. );
  25. -- mysals表使用fba2策略归档
  26. alter table mysales flashback archive fba2;

测试:

  1. -- 执行一些增删改操作
  2. -- 更换undo表空间,确认闪回的数据不是来自于undo
  3. create undo tablespace undotbs2 datafile '+data' size 100M;
  4. alter system set undo_tablespace='UNDOTBS2';
  5. drop tablespace undotbs1 including contents and datafiles;
  6. -- 进行闪回查询,可以从闪回归档中查询到之前的数据
  7. -- 查看闪回的执行计划,可以看到查询的是 sys_fba_hist_77429sys_fba_tcrv_77429这些闪回归档的系统表

闪回归档的相关视图:

  1. -- 闪回表空间信息
  2. select * from dba_flashback_archive_ts;
  3. -- 闪回归档策略信息
  4. select * from dba_flashback_archive;
  5. -- 启用闪回归档的表信息,以及这些表对应的闪回归档表
  6. select * from dba_flashback_archive_tables;

闪回归档的基表:

  1. -- 一个表做了闪回归档后,oracle会为该表生成3个闪回归档的基表
  2. -- 查看T表的Object_ID,例如 73201
  3. select object_id from dba_objects where object_name='T';
  4. -- t表如果做了闪回归档,oracle会为该表生成3个表
  5. select * from sys_fba_ddl_colmap_73201; -- 记录对t表字段做的ddl操作
  6. select * from sys_fba_tcrc_73201; -- 记录对t表的每一次事务改变的数据信息
  7. select * from sys_fba_hist_73201; -- 表实际的每个字段改变的数据

修改闪回归档的策略信息操作:

  1. alter flashback archive fba1 modify tablespace his_data_1 quota 250M;
  2. alter flashback archive fba1 modify retention 1 day;
  3. drop flashback archive fba1;
  4. alter table t no flashback archive;

当数据超过设定的保留期限后,会自动删除。

也可以手工删除:

  1. alter flashback archive fba1 purge all;
  2. alter flashback archive fba1
  3. purge before timestamp (systimestamp - interval '1' day);
  4. alter flashback archive fba1
  5. purge before scn 528967;

数据库层面的闪回

数据库的闪回是Oracle不同于查询闪回和闪回归档的另外一种闪回机制,从10g时引入。需要配置闪回区域。记录修改的数据块,称为flashback logs。通过后台进程 RVWR 来工作。

数据库的闪回可以让数据库向后回退,可以用于人为失误操作或者业务的需要。

数据库闪回的架构:

在内存的SGA区内,开辟一个 Flashback buffer,用来记录 Buffer Cache的改变。

但是和Redo log buffer不同,redo log buffer会记录buffer cache中的每一次改变,flashback buffer 只会隔一段时间搜集一次 buffer cache的改变。

通过 RVWR 进程,将 flashback buffer中的数据写到磁盘 flashback logs中。

数据库闪回时,先从 flashback logs中读取闪回的内容,但是因为flashback logs是隔一段时间记录一次,里面的数据并不完整,所以在读完 flashback logs之后,还需要再读取一小块的 redo logs 的数据。

闪回日志:

日志位置:xxx/app/用户名/flash_recovery_area/实例名/FLASHBACK下的flb后缀文件。

日志文件名是Oracle自己命名管理的(Oracle Managed Files, OMF)。

日志在闪回的过程中是顺序被使用的。

当空间不足时,闪回日志会被覆盖。

RVWR进程:

  • 将产生的闪回数据copy到闪回日志中
  • 每三秒检查一次新的闪回数据

配置数据库闪回功能:

  1. 配置闪回区域
  2. 设定闪回时长
  3. 启动闪回功能
  1. shutdown immediate;
  2. -- 启动到mount状态
  3. startup mount exclusive;
  4. alter system set db_flashback_retention_target=2880 scope=BOTH;
  5. alter database flashback on;
  6. -- 打开数据库
  7. alter database open;
  8. -- 查看数据库是否启用了闪回
  9. select flashback_on from v$database;

数据库闪回的前提:

  • 数据库必须归档
  • 闪回去必须指定:DB_RECOVERY_FILE_DEST_SIZE指定闪回去大小,DB_RECOVERY_FILE_DEST指定闪回区的位置。

比如:

  1. alter system set db_recovery_file_dest_size = 10G;
  2. alter system set db_recovery_file_dest = '/oradata/recovery';

闪回相关的时间和SCN:

  1. -- 当前SCN
  2. select current_scn from v$database;
  3. -- 允许闪回的最早SCN
  4. select oldest_flashback_scn from v$flashback_database_log;
  5. -- 允许闪回的最早时间
  6. alter session set nls_date_format = 'DD-MON-YYYY HH24:MI:SS';
  7. select oldest_flashback_time from v$flashback_database_log;

保证还原点:还原点能保证在任何时候将数据库通过 flashback database命令还原到这个时间点(SCN)。

  1. -- 在当前时间创建一个保证还原点
  2. create restore point b4_load
  3. guarantee flashback database;

闪回数据库的语句:

在RMAN里执行:

  1. flashback database to time = "TO_DATE('2021-05-27 16:00:00', 'YYYY-MM-DD HH24:MI:SS')";
  2. flashback database to SCN=23565;
  3. flashback database to sequence=223 thread=1; -- 闪回到指定序号的日志

在SQL里执行:

  1. flashback database to timestamp(SYSDate - 1/24); -- 闪回到1个小时前
  2. flashback database to SCN=23565;
  3. flashback database to restore point b4_load;

无论使用哪个语句,在数据库闪回之后,打开数据库时都需要重置日志:

  1. -- 因为数据库闪回之后,数据库的序号和日志文件的序号不一致了,需要重置数据库日志
  2. alter database open resetlogs;
  3. -- 重置之后,日志序号又会从1开始。如果rman是使用的增量备份,那么基于日志序号的备份就会受到破坏,因此需要用rman对日志、控制文件再做一次全量备份

flashback发展历程

9i :flashback query

10g:flashback version query、flashback table、flashback database

11g:flashback data archive、flashback transaction backout