Oracle 闪回技术(标准版 Oracle 数据库不支持闪回)
为什么使用闪回技术?
为了使数据库能够从任何逻辑错误中迅速恢复,Oracle 推出了闪回技术。采用该技术,可以对行级和事物级的数据变化进行恢复,减少了数据恢复的时间,而且操作简单。通过 SQL 语句就可以实现数据的恢复,大大提高了数据库恢复的效率。闪回技术是数据库恢复技术历史上一次重大的进步,从根本上改变了数据恢复。
闪回技术包括以下各项
闪回查询:(FLASHBACK QUERY):查询过去某个时间点或某个 SCN 值时表中的数据信息
闪回版本查询(FLASHBACK Version query):查询过去某个时间段或某个 SCN 段内表中数据变化的情况。
闪回事物查询(FLASHBACK Transaction Query): 查看某个事物或所有事物在过去一段时间对数据进行的修改。
闪回数据库(FLASHBACK Database):将数据库恢复到过去某个时间点或某个 SCN 值时的状态
闪回删除(FLASHBACK drop):将已经删除的表及其关联的对象恢复到删除前的状态。
闪回表(FLASHBACK table):将表恢复到过去的某个时间点或某个 SCN 值时的状态。
SCN 是当 Oracle 数据库更新后,有 DBMS 自动维护而累积递增的一个数字。可以通过查询数据字典V $DATABASE 中的 CURRENT_SCN 获得当前的 SCN 号。
闪回恢复区的含义
Oracle 推荐指定一个闪回恢复区(FLASHRECOVERY AERA)作为存放备份与恢复相关的默认位置,这样 Oracle 就可以实现自动的基于磁盘的备份与恢复。闪回恢复区是一块用来存储恢复相关的文件的存储空间,允许用户集中存储所有恢复相关的文件。
以下几种文件可以存放在闪回恢复区
控制文件
归档日志文件
闪回日志
控制文件和SPFILE自动备份
RMAN备份集
数据文件拷贝
闪回恢复区主要通过以下3个初始化参数来设置和管理
db_recovery_file_dest:指定闪回恢复区的位置
db_recovery_file_dest_size:指定闪回恢复区的可用空间
db_flashback_retention_target:该参数用来控制闪回日志中数据保留的时间,或者说,希望闪回数据库能够恢复到的最早的时间点。单位为 min,默认是 1440 min,即一天。当然实际上可回退的时间还取决于闪回恢复区的大小,因为里面保存了回退所需要的闪回日志,所以这个参数要 和 db_recovery_file_dest_size 配合修改。
如果要撤销闪回恢复区,把初始化参数DB_RECOVERY_FILE_DEST的值清空。
db_recovery_file_dest_size只有在DB_RECOVERY_FILE_DEST清空之后才可以清空
设置闪回数据库
设置了闪回恢复区,要启动闪回数据库功能,还需要进一步配置,数据必须处于归档模式,在设置闪回数据库
数据库已经处于归档模式
archive log list;
数据库未启用闪回数据库
select flashback_on from v$database;
建立闪回区域并配置其空间
alter system set db_recovery_file_dest= '/u01/app/oracle/flash_recovery_area' scope=spfile;
alter system set db_recovery_file_dest_size=8G scope=spfile;
设置闪回数据库的数据保留周期为一天以 min 为单位
alter system set db_flashback_retention_target=1440;
启用闪回日志
alter database flashback on;
查询是否成功启用闪回恢复区
show parameter db_recovery_file;
查询是否成功启用闪回数据库
闪回数据库
闪回数据库能够使数据迅速的回滚到以前的某个时间点或者某个 SCN 上,这对数据库从逻辑错误中恢复特别有用。而且也是大多数发生逻辑损坏时恢复数据库最佳的选择。
使用 SCN 闪回数据库
查看数据库系统当前 SCN
select current_scn from v$database;
--不会影响原有的最新值,这个可以在程序中使用
SQL>select dbms_flashback.get_system_change_number() from dual;
--SQL只要执行一次 SCN 就会在原有的最新值的基础上加1,和序列号的 nextval 相似
SQL>select current_scn from v$database;
改变数据库当前状态,模拟创建表 flashback_test ,并插入一条记录
create table flashback_test (id int);
insert into flashback_test values(1);
commit;
进行闪回数据库恢复,先将数据库重启,启动至 mount 状态,将数据库恢复到创建表之前的状态,即 SCN 为 1421765
用 RESETLOGS 选项打开数据库 resetlogs 为重新记录日志
alter database open resetlogs;
验证数据库的状态,flashback_tes 表不存在
查询数据库中当前最早的闪回 SCN 和时间
-- 该语句为调整时间格式
alter session set nls_date_format='YYYY-MM-DD HH24:MI:SS';
select oldest_flashback_scn,oldest_flashback_time from v$flashback_database_log;
按照指定时间闪回数据库
查询数据库中当前时间和当前 SCN
改变数据库的当前状态,模拟创建表 test11 ,并插入1条记录
-- 显示时间
set time on
create table flashback_test1 (id int);
insert into flashback_test values(10);
commit;
进行闪回数据库恢复,将数据库恢复到插入数据之前的状态
flashback database to timestamp(to_timestamp('2020-01-23 21:16:56','YYYY-MM-DD HH24:MI:SS'));
使用 RESETLOGS 打开数据库
验证数据库的状态 flashback_test1 数据是否存在
闪回数据库操作的限制
1、数据文件损坏或丢失等介质故障不能使用闪回数据库进行恢复。闪回数据库只能基于当前正常运行的数据文件。
2、闪回数据库功能启动后,如果发生数据控制文件重建或利用备份恢复控制文件,则不能使用闪回数据库。
3、不能使用闪回数据库进行数据文件收缩操作。
4、不能使用闪回数据库将数据库恢复到在闪回日志中可获得的最早的 SCN 之前的 SCN,因为闪回日志文件在一定的条件下被删除,而不是始终保存在闪回恢复区中。
闪回表
闪回表是将表恢复到过去的某个时间点或者指定的 SCN 而不用恢复数据文件,为 DBA 提供了一种在线、快速、便捷的恢复方式,可以恢复对表进行的修改、删除、插入等错误的操作。
利用闪回表技术恢复表中的数据的过程,实际上是对表进行DML操作的过程。Oracle 自动维护与表相关联的索引、触发器、约束等。
为了使用数据库闪回功能,必须满足下列条件
1、用户具有 FALSHBACK ANY TABLE 系统权限,或者具有所操作表的 FLASHBACK 对象权限
2、用户具有所操作表的 SELECT/INSERT/DELETE/ALTER 对象权限
3、启动被操作表的 ROW MOVEMENT 特性,可以采用下列方式进行:
-- 开启行迁移
ALTER TABLE 表名 ENABLE ROWMOVEMENT;
闪回表语法格式
FLASHBACK TABLE [schema].table TO SCN |TIMESTAMP expression [ENABLE|DISABLE TRIGGERS]
参数说明:
SCN: 将表恢复到指定的 SCN 时的状态
TIMESTAMP: 将表恢复到指定额时间点
ENABLE|DISABLETRIGGERS: 在恢复表中数据的过程中,表上的触发器时禁用还是激活(默认是引用)
举例说明
使用 SCOTT 用户登录
创建表,插入记录,提交事物
create table scott_test (id number(10));
insert into scott_test values(1);
insert into scott_test values(2);
insert into scott_test values(3);
commit;
查询当前 SCN 号,如果当前用户没有权限查询 v$database,则以 sys 用户登录,授予当前用户访问数据字典的权限
-- 不是所有的用户都可以直接查询 v$database 数据字典
select current_scn from v$database;
-- 以下查询 scn 的方式需要用户拥有 dbms_flashback 的权限
-- 权限的授予方式: grant execute on dbms_flashback to scott;
select dbms_flashback.get_system_change_number as scn from dual;
更新记录,并提交事务
update scott_test set id =100 where id=1;
查看表中的记录
select * from scott_test;
删除 ID=3 的记录 并查看数据
delete from scott_test where id = 3;
select * from scott_test;
启动 scott_test 表的 ROW MOVEMENT 特性
alter table scott_test enable row movement;
将 scott_test 表恢复到 delete 之前的数据
flashback table scott_test to timestamp to_timestamp('2020-01-23 21:43:01','YYYY-MM-DD HH24:MI:SS')
将 scott_test 表恢复到 SCN 为 1426432 的状态
flashback table scott_test to scn 1426432;
闪回删除
闪回删除可以恢复使用 DROP table 语句删除的表,是一种对意外删除的表恢复机制。闪回删除的功能的实现主要是通过 Oracle 数据库中的 “回收站” 技术实现的。在 Oracle 数据库中,当执行 DROP table 操作时,并不立即收回表及其关联对象的空间,而是将他们重命名后放入一个称为 “回收站” 的逻辑容器中保存,直到用户决定永久删除他们或存储该表的表空间或存储空间不足时,表才真正被删除,为了使用数据库的闪回删除技术,必须开启数据库的”回收站”
启动 “回收站” 将参数 RECYCLEBIN 设置为 ON,在默认情况下”回收站”已经启动
show parameter recyclebin;
如果没有启动可以使用
alter system set recyclebin= on deferred;
查看回收站,当执行 DROP table 时,表及关联的对象被命名后保存在 “回收站” 中,可以通过查询 USER_RECYCLEBIN DBA_RECYCLEBIN 视图获得被删除的表及其关联对象
通过 USER_RECYCLEBIN 查看被删除的表
select object_name ,original_name,type from user_recyclebin;
不支持 sys 用户和 system 用户,这两个用户下的表被删除之后,无法从回收站里拿到,查询时为 “空”
如果删除表的时候使用了 PURGE 短语,则表及其关联对象呗直接释放,空间被回收,相关信息不会进入 “回收站” 中
清空回收站
由于被删除的表级其关联对象信息保存在 “回收站” 中,其存储空间并没有释放,因此需要定期清空 “回收站” 。或清除 “回收站” 中没有用的对象(表,索引,表空间)释放其所占用的磁盘空间
语法如下
PURGE [TABLE 表名 | INDEX index]
[RECYCLEBIN | DBA_RECYCLEBIN] | [TABLESPACEtablespace [USER user]]
参数说明
TABLE:从回收站中清除指定的表
INDEX:从回收站中清除指定的索引,并回收其磁盘空间
RECYCLEBIN:清空用户“回收站”,并回收所有对象的磁盘空间
DBA_RECYCLEBIN:清空整个数据库系统的“回收站”,只有具有SYSDBA权限的用户才可以使用
TABLESPACE :清除“回收站”中指定额表空间,并回收磁盘空间
USER:清除回收站中指定表空间中特定用户的对象,并回收磁盘空间
闪回删除操作,闪回删除的基本语法
FLASHBACK TABLE [schema.]table to BEFOREDROP [RENAME TO table]
闪回删除
flashback table xxa to before drop;
闪回删除举例说明
flashback table xxa to before drop rename to newxxa;
flashback table “BIN$m/Paxk/0Ln/gUwMKqMBVSg==$0” to before drop rename to new_test;
闪回查询
允许根据时间点 timestamp 或 SCN 查看就的数据,除了可以查看旧数据,需要时可以通过检索旧数据来撤销错误的更改。
使用 SCOTT 用户登录,对 EMP 表基于AS of TIMESTAMP 的闪回查询
-- 设置时间显示
set time on
22:05:49
22:07:41 更新员工号为 3 ,更新为 niuniu,并提交事物
22:07:41 更新员工号为 3,更新两次,提交事物
22:09:32 更新员工号为 3,更新为 daerzi,并提交事物
22:09:47 查看 3 号员工的更新后名字
查询 3 号 2020-1-23 22:05:49 时的名字
select * from emp as of timestamp to_timestamp('2020-1-23 22:05:49','YYYY-MM-DD HH24:MI:SS');
查询第一个事物提交,第二个事物还没有提交时
select * from emp as of timestamp to_timestamp('2020-1-23 22:07:45','YYYY-MM-DD HH24:MI:SS');
如果需要,可以将数据恢复到过去某个时刻的状态
update emp set name= (select name from emp as of timestamp to_timestamp('2020-1-23 22:05:49','YYYY-MM-DD HH24:MI:SS') where id=3) where id=3;