文章目录
1. 概述
闪回技术是Oracle备份恢复机制的一部分,主要解决逻辑错误的恢复问题,无法解决物理损坏造成的故障。在实际工作中更多的用在开发及测试阶段,生产环境下要谨慎使用。
2. 闪回类型及原理
闪回类型 | 原理 |
---|---|
flashback drop 闪回删除 | RECYCLEBIN 回收站 |
flashback query 闪回查询 | UNDO 数据 |
flashback table 闪回表 | UNDO 数据 |
flashback version query 闪回版本查询 | UNDO 数据 |
flashback transaction 闪回事务 | UNDO 数据 |
flashback data archive 闪回归档 | Archive Log 归档 |
flashback database 闪回数据库 | Flashback Database Log 闪回日志 |
3. 闪回删除
3.1. 回收站
Oracle 从10g开始引入了回收站(RECYCLEBIN)的概念。它实际上是一个逻辑容器,没有固定的物理存储空间,与表空间中的对象公用物理存储空间。因此,当表被 DROP 后,如果表空间空间充足,且没有对回收站进行清理,那么被 DROP 掉的对象会一直保存在回收站中(有点类似于数据库使用中常用到的逻辑删除,只是打上了删除标记)。当表空间空间不足的时候,数据库会根据先进先出的顺序覆盖回收站中的对象,需要注意的是,这种覆盖是以对象为单位的,不存在部分对象的情况。
该功能由初始化参数 recyclebin 控制,当值为 on 时开启,值为 off 时关闭,默认值为 on。
show parameter recyclebin
3.2. 回收站中对象的操作
对回收站中的对象可以进行闪回和清除操作,需要注意的是闪回和清除的顺序不同:
- 闪回使用 LIFO (后进先出)
- 清除使用 FIFO (先进先出)
3.3. 示例
闪回操作
-- 可以直接通过回收站中的名字进行查询,确认是否是需要的数据
select count(*) from "BIN$nBW14MjkYtzgUxUJqMBbHw==$0";
-- 确认是需要的数据的时候可以将回收站中的对象恢复
flashback table t1 to before drop;
清除操作
-- 清除后将无法再恢复
purge table t1;
3.4 相关操作及注意事项
如果想避免混淆,可以直接指定回收站中的表名:
flashback table "BIN$fNCNfmfYwQLgU8kKqMCzLA==$0" to before drop;
purge table "BIN$fNCNfmfYwQLgU8kKqMCzLA==$0";
清空回收站
purge recyclebin;
把闪回删除的对象重命名
flashback table "BIN$fNCNfmfYwQLgU8kKqMCzLA==$0" to before drop rename to t3;
system 表空间的对象没有回收站, sys 缺省使用 system 表空间,drop table 时会直接删除对象。
索引和约束在恢复后,名称会乱码,需要手动修改名称
select * from user_indexes;
select * from user_constraints;
alter index "BIN$yF3hbvIbioTgQAB/AQAJlg==$0" rename to t1_indx;
alter table t1 rename constraint "BIN$yF3hbvIbioTgQAB/AQAJlg==$0" to t1_pk;
4. 闪回查询
4.1. 作用
适用于 DML 误操作。利用 UNDO 里未被覆盖的数据,可以查询表的过去某个时间点的数据。通过设置 undo_retention 参数,可以控制前镜像的保留时间。
4.2. 语法
select … as of scn | timestamp;
4.3. 示例
-- 准备数据
create table t1 as select * from jobs;
-- 这是 t1 表开始时的数据,共19条数据
select * from t1;
-- 记录开始时刻(SCN 1)
select current_scn from v$database;
select to_char(sysdate,'YYYY-MM-DD HH24:MI:SS') n_time from dual;
-- 删除一些数据
delete t1 where job_id like 'AD%';
commit;
-- 记录了删除数据后的时刻,此时剩余16条数据(SCN 2)
select current_scn from v$database;
select to_char(sysdate,'YYYY-MM-DD HH24:MI:SS') n_time from dual;
-- 将 min_salary 列全部改为了 10000
update t1 set min_salary=10000;
commit;
-- 现在看到的是最终数据
select * from t1;
-- 查询到最开始时的数据(SCN 1)
select * from t1 as of scn 4496826;
select * from t1 as of timestamp to_timestamp('2020-01-14 16:17:26','YYYY-MM-DD HH24:MI:SS');
-- 查询到执行过删除,尚未进行更新时的数据(SCN 2)
select * from t1 as of scn 4496868;
select * from t1 as of timestamp to_timestamp('2020-01-14 16:18:36','YYYY-MM-DD HH24:MI:SS');
总结
通过该示例我们可以发现,只要 UNDO 数据不被覆盖,我们可以闪回查询到过去任意时刻的数据,这对于人为误操作的处理极为有用。
5. 闪回表
5.1. 作用
闪回表可以把表的状态闪回到某个时刻或者 SCN 上,既可以向前闪回,还可以向后闪回(闪回到的时刻早了)。该技术必须对表启用行移动。
5.2. 语法
-- 是能行移动
alter table tablename enable row movement;
flashback table tablename to scn | timestamp;
5.3. 示例
该示例数据接上一个 4.3 的示例
-- 将 t1 表的数据全部删除并使能行移动
delete t1;
commit;
alter table t1 enable row movement;
-- 闪回表到最初时刻
flashback table t1 to timestamp to_timestamp('2020-01-14 16:17:26','YYYY-MM-DD HH24:MI:SS');
select * from t1 ;
-- 将表 t1 闪回到 SCN2 的时刻,也就是删除过3行数据后的时刻
flashback table t1 to timestamp to_timestamp('2020-01-14 16:18:36','YYYY-MM-DD HH24:MI:SS');
select * from t1 ;
-- 将表 t1 闪回到删除前的时刻,也就是上一个示例最终的时刻
flashback table t1 to timestamp to_timestamp('2020-01-14 16:40:36','YYYY-MM-DD HH24:MI:SS');
select * from t1 ;
总结
把表闪回到过早的时刻后,还可以向后闪回。闪回表直接操作了表数据,生产环境谨慎使用。
5.4. 注意事项
- sys 的表不能闪回;
- 必须使能行移动;
- 缺省下,闪回表的过程中有关的 trigger 都关闭(可以使用 ENABLE TRIGGERS 关键字指定触发器有效);
- 闪回表 index 是被维护的;
- 表结构不能改变;
- 物化视图、远程表、系统表、单个分区等特殊的表不能进行闪回;
6. 闪回版本查询
6.1. 作用
闪回版本查询可以对指定时间段内数据表的每行变化(不同版本)进行查询。如果想要获得 UNDO SQL(闪回事务查询),则需要开启附加日志
6.2. 语法
select … from … versions between … and …
-- select 后面可以选择伪列,来获得事务的开始、结束时间,SCN 号、ID 号等。
6.3. 示例
-- 开启附加日志,为闪回事务查询做准备
alter database add supplemental log data;
-- 准备数据
create table t2 as select * from regions;
select * from t2;
-- 对数据进行一系列操作
delete t2 where region_id=1;
commit;
update t2 set region_name='CHINA' where region_id=3;
commit;
update t2 set region_id=region_id+100;
commit;
-- 闪回版本查询
select versions_startscn,versions_endscn,versions_xid,versions_operation,region_id,region_name from t2 versions between scn minvalue and maxvalue;
Oracle 闪回版本查询行数据伪列说明(官方文档)
7. 闪回事务查询
7.1. 作用
闪回事务查询可以提供撤销查询语句。从 flashback_transaction_query 这个视图里查询引起数据变化的事务,和撤销事务的 SQL 语句,也就是查询 operation 和 undo_sql 列。可以和闪回版本查询结合起来使用。
7.2. 示例
desc flashback_transaction_query;
SELECT undo_sql FROM flashback_transaction_query WHERE xid = HEXTORAW('0A001C00260F0000');
执行上面的语句,原操作(update t3 set id=id+100;)就撤销了
7.3. 注意事项
- 需要开启附加日志(alter database add supplemental log data;)
- 查询 flashback_transaction_query 视图需要 select any transaction 权限
8. 闪回数据归档
8.1. 作用
闪回查询对 UNDO 的依赖注定了它们在大事务量的情况下闪回时间窗口将会很小,如果想要对重点表的数据进行长时间的闪回查询,就要用到闪回数据归档技术。闪回数据归档可以将表行的历史数据长期存储起来。它通过后台进程 FBDA ,捕捉必要的数据并将其保存在归档上,然后可以使用常规闪回查询命令( as of )查询需要的数据,可以看作是闪回查询的延伸。
8.2. 要点
- 要有一个(或多个)表空间存放归档表,使用与原表同一表空间在技术上是可行的,但是 Oracle 建议他们与常规数据分开存放。
- 建立一个归档名,作为一个数据库的对象,可以为它指定 default 属性,含义是把所以后要归档的表都建立在该缺省的归档名下。
- 可以根据需要建立多个闪回归档名,这取决于你需要多少种不同的保留时间,一旦超过保留期限,后台进程 FDBA 将自动删除该表的历史记录,也可以在保留期内手动进行删除操作。
- 闪回归档 enable 的前提条件,表空间要 ASSM 管理,undo_management=auto。
相关权限
权限名 | 权限作用 |
---|---|
flashback archive administer | 授予用户创建、修改和删除闪回归档名的权限 |
flashback archive | 授予用户对表进行归档的权限 |
相关视图
视图名 | 视图说明 |
---|---|
DBA_FLASHBACK_ARCHIVE | 描述配置的归档 |
DBA_FLASHBACK_ARCHIVE_TS | 列出使用的表空间 |
DBA_FLASHBACK_ARCHIVE_TABLES | 查看归档的表 |
语法格式
-- 需要首先创建归档表空间和归档,此处的归档名是指创建号的归档的名称
alter table 表名 flashback archive 归档名;
8.3. 示例
-- DBA 创建表空间,创建闪回归档并授权
create tablespace fda datafile '/oradata/ORA19C/pamsdb/fda01.dbf' size 50M;
create flashback archive fla1 tablespace fda retention 1 year;
grant flashback archive on fla1 to hr;
-- 用户为自己的表开启闪回归档,这样 T2 表上的闪回数据就会在表空间 fda 上保存一年的时间
alter table t2 flashback archive fla1;
-- 查看相关视图,通过查询以下视图,可以获得当前的闪回数据归档情况
select * from dba_flashback_archive;
select * from dba_flashback_archive_ts;
select * from dba_flashback_archive_tables;
-- 取消闪回数据归档。当不需要的时候可以取消闪回数据归档
alter table scott.emp no flashback archive;
总结
闪回数据归档是典型的以空间换容错的技术,如果某表数据特别重要,为了防止人为逻辑故障的发生,可以对该表进行闪回数据归档,但绝不建议对大多数表进行闪回数据归档,因为会产生大量的额外空间及性能开销。
9. 闪回数据库
9.1. 作用
闪回数据库可以将数据库整体回退到某个时间点(是不是跟 RMAN 做不完全恢复很像,但是不一样哦)。闪回数据库针对的是逻辑错误,如果数据库发生了物理损坏,闪回数据库将无能为力。
闪回数据库需要用到闪回日志,闪回日志存放在闪回恢复区。开启闪回日志后,某些块的映像会从 db buffer 中复制到闪回缓冲区,然后再由后台进程( Recover Write RVWR )将此闪回恢复区的内容刷新到磁盘的闪回日志。与重做日志不同的是闪回日志不是记录的数据库所有变化,而是记录完整块映像的记录。
9.2. 闪回恢复区
闪回恢复区( flash recovery area )是从 10g 版本引入的一个非常重要的概念,它不仅存放闪回日志,还有许多与恢复相关的文件。
例如可以存放与 RMAN 相关的三种自动管理的文件:
- 归档日志
- 控制文件自动备份
- RMAN 备份片
当 flash recovery area 空间不够时,Oracle 还可以自动清除一些废弃( obsolete )文件。
相关参数
show parameter db_recovery_file_dest
show parameter db_flashback_retention_target
设置 db_recovery_file_dest 之前必须先设置 db_recovery_file_dest_size ;
db_flashback_retention_target 用来设置闪回日志的保留期,默认值 1440 ,单位是分钟。
9.3. 开闪回
-- 查看是否开启闪回数据库
select flashback_on from v$database;
-- 创建目录、赋予权限
$ mkdir /oradata/flash_recovery_area
$ ls -ld /oradata/flash_recovery_area
-- 修改初始化参数,生产环境一定要注意,db_recovery_file_dest_size 必须根据实际情况设置的足够大
alter system set db_recovery_file_dest_size=4G;
alter system set db_recovery_file_dest='/oradata/flash_recovery_area';
show parameter db_recovery_file_dest
show parameter db_flashback_retention_target
-- 开闪回。开闪回之前要开归档
archive log list
alter database flashback on;
select flashback_on from v$database;
9.4. 示例
-- 取当前 SCN,作为闪回目标
select current_scn from v$database;
select to_char(sysdate,'YYYY-MM-DD HH24:MI:SS') n_time from dual;
-- 也可以创建一个还原点
create restore point rp1;
-- 删除 hr 用户
drop user hr cascade;
-- 启动到 mount 下做闪回数据库
shut immediate
startup mount
-- 闪回到 rp1 闪回点
flashback database to restore point rp1;
-- 或者也可以用 SCN 或者 timestamp 闪回
flashback database to scn 2802872;
flashback database to timestamp to_timestamp('2020-01-14 17:16:16', 'YYYY-MM-DD HH24:MI:SS');
-- 只读方式打开,确认 hr 已经被闪回
alter database open read only;
select table_name from dba_tables where owner='HR';
select open_mode from v$database;
-- 确认无误后,以 resetlogs 方式打开数据库
shut immediate
startup mount
alter database open resetlogs;
select open_mode from v$database;
-- 一旦 resetlogs 打开,只能闪回到比当前更早的 SCN。
-- 所以闪回后,第一次最好以只读方式打开,检查是否恢复到你希望的那个时间点上。如果不是你希望的,还可以重新闪回(前闪/后闪都可以)。