第14章 闪回技术(Flashback)
闪回技术是oracle提供的7个能使数据库整体或局部回到过去的闪回功能总称
- 闪回查询
- 闪回数据归档
- 闪回事务查询
- 闪回事务
- 闪回表
- 闪回删除
- 闪回数据库
闪回查询能在撤销段内搜索旧数据,数据库能保留多少旧数据决定了闪回查询的时间窗口大小。以下4个因素决定
- 初始化参数undo_retention(默认900秒)
- undo表空间是否启用了自动增长
- undo表空间是否绝对尊重参数undo_retention的设置(默认不尊重900秒以上的设置)
- 数据库中的事务量
总之,闪回时间窗口有多大,取决于数据库能容忍多大的undo表空间,即用空间换过去的时间。
# 检查初始化参数undo_retention
show parameter undo_retention
# 修改保留时间为3600秒
alter system set undo_retention=3600;
# 检查undo表空间是否启用自动增长
select autoextensible from dba_data_files
where tablespace_name=
(select value from v$parameter where name ='undo_tablespace');
# undo表空间是否绝对尊重参数undo_retention的设置
select retention from dba_tablespaces
where tablespace_name='UNDOTBS1';
# 设置undo表空间绝对尊重参数undo_retention
alter tablespace undotbs1 retention guarantee;
闪回查询
# 查询固定时间点数据表的记录
select * from hr.employees
as of timestamp to_timestamp('2024-06-13 10:58:00','YYYY-MM-DD HH24:MI:SS')
where employee_id=202;
# 查询10分钟前数据表的记录
select * from hr.employees
as of timestamp (systimestamp - interval '10' minute)
where employee_id=202;
# 查询之前某个SCN数据表的记录
select * from hr.employees
as of scn 1243223
where employee_id=202;
# 将10分钟前某表与1小时前另一张表关联查询
select e.last_name,d.department_name
from hr.employees as of timestamp (systimestamp - interval '10' minute) e,
hr.departments as of timestamp (systimestamp - interval '1' hour) d
where e.department_id=d.department_id;
# 将某个字段修改为15分钟前的值
update hr.employees
set email=(select email from hr.employees
as of timestamp (systimestamp - interval '15' minute)
where employee_id=202)
where employee_id=202;
# 模拟数据更新
update hr.employees set salary=4100 where EMPLOYEE_ID=200;
update hr.employees set salary=4200 where EMPLOYEE_ID=200;
update hr.employees set salary=4300 where EMPLOYEE_ID=200;
# 闪回版本查询(可以查询变更顺序)
select versions_xid,versions_startscn,versions_endscn
,versions_starttime,versions_endtime,employee_id,salary
from hr.employees
versions between timestamp (systimestamp - interval '10' minute) and maxvalue
where EMPLOYEE_ID=200
order by 2 nulls first;
闪回数据归档
原理:将原本只能保存在undo表空间的撤销数据额外的以一种历史表的形式保存在指定的普通表空间中,可以只针对特定的表而不是整个数据库。
# 在users表空间中创建一个可以保存1年旧数据的数据归档
create flashback archive fda1 tablespace users retention 1 year;
# 在特定表上启用闪回数据归档功能
alter table hr.employees flashback archive fda1;
# 创建新表时就指定闪回数据归档
create table hr.tb01(id int,name varchar2(100)) flashback archive fda1;
# 关闭闪回数据归档功能
alter table hr.employees no flashback archive;
# 限制闪回数据归档的空间大小
create flashback archive fda2 tablespace users quota 40G retention 1 year;
# 清除闪回数据归档中一个月之前的数据
alter flashback archive fda1 purge before timestamp (systimestamp - interval '1' month);
# 清除闪回数据归档中所有数据
alter flashback archive fda1 purge all;
闪回事务查询
与闪回查询不同的地方有以下3个:
- 需要启用最小补充日志
- 返回的结果不是旧数据,而是可以将当前数据修改为以前样子的SQL语句
- 集中地在名为flashback_transaction_query表上查询,而不是在各个表上通过as of等查询
# 启用最小补充日志
alter database add supplemental log data;
# 修改数据表
create table hr.test01 (id int,name varchar2(100));
insert into hr.test01 values (1,'zs');
insert into hr.test01 values (2,'ls');
insert into hr.test01 values (3,'ww');
delete hr.test01 where id=2;
update hr.test01 set name = 'zsf' where id = 1;
# 检查表数据
select * from hr.test01;
# 检查表数据
select * from hr.test01;
# 闪回版本查询 versions_xid 表示事务号
select versions_xid,versions_startscn,versions_endscn
,versions_starttime,versions_endtime,id,name
from hr.test01
versions between timestamp minvalue and maxvalue
order by 2 nulls first;
# 查询闪回事务,注意 UNDO_SQL 字段,可用于DML还原操作,DDL不行。
select * from flashback_transaction_query where table_name='TEST01' order by commit_scn desc,UNDO_CHANGE#;
闪回事务
闪回事务又叫做撤销事务,可以自动撤销事务,无需手工执行undo_sql。
由 DBMS_FLASHBACK.TRANSACTION_BACKOUT 存储过程实现。
前提:至少需要启用主键补充日志,为了能够跟踪外键依赖,还需要启用外键补充日志。
事务的依赖性:257页
# 检查表初始数据
select employee_id,first_name,last_name,salary from hr.EMPLOYEES;
# 假设执行了误操作
update hr.EMPLOYEES set salary = salary*5;
commit;
update hr.EMPLOYEES set salary = salary*1.1 where employee_id=100;
commit;
# 查询该表15分钟内的事务
select distinct xid,commit_scn
from FLASHBACK_TRANSACTION_QUERY
where table_owner='HR' and
table_name='EMPLOYEES' and
commit_timestamp > systimestamp - interval '15' minute
order by commit_scn;
# 根据事务号查询闪回事务查询信息 1113044对应第一个事务,1113046对应第二个
select undo_sql from flashback_transaction_query where commit_scn='1113044';
# 撤销事务(两个事务存在关联性,最好是一同撤销) 04001E00D4020000 为第一个事务xid
declare
xids sys.xid_array;
begin
xids:=sys.xid_array('04001E00D4020000');
DBMS_FLASHBACK.TRANSACTION_BACKOUT(1,xids,options=>dbms_flashback.cascade);
end;
/
# 再次检查表数据发现还原了
select employee_id,first_name,last_name,salary from hr.EMPLOYEES;
# 最后别忘了提交事务
commit;
闪回表
闪回表能够以表为单位将数据表恢复成以前的样子(区别于闪回事务的以事务为单位)
必须启用行移动功能
闪回数据归档不能为闪回表服务,闪回表只能使用undo表空间的撤销数据
# 启用行移动功能
alter table hr.employees enable row movement;
# 将表恢复到10分钟前(自动commit)
flashback table hr.employees to timestamp (systimestamp - interval '10' minute);
闪回删表
闪回删表是指撤销drop table的操作
drop table的操作并没有真正删除表数据和索引,甚至数据块都没有移动,只是将他们分配到了回收站中。
如果数据文件自动增长了,则表示回收站中的对象已经全部失效。
# 模拟误操作删表
DROP TABLE hr.EMPLOYEES;
# 查询回收站信息
select * from dba_recyclebin;
# 查询回收站中表的数据 object_name 用双引号括起来
select * from "BIN$GsFJ+yclG93gYw+FqMDooA==$0";
# 恢复表(有同名表时可以指定object_name)
flashback table hr.EMPLOYEES to before drop;
flashback table "BIN$GsFJ+yclG93gYw+FqMDooA==$0" to before drop;
# 彻底删除表(不进入回收站)
DROP TABLE hr.EMPLOYEES purge;
# 删除一个特定的回收站对象
purge table "BIN$GsFJ+yclG93gYw+FqMDooA==$0";
# 清空当前用户回收站
purge user_recyclebin;
# 清空users表空间中所有的回收站对象
purge tablespace users;
# 清空整个数据库中所有的回收站对象
purge dba_recyclebin;
# 禁用回收站功能,重启实例生效
alter system set recyclebin='off' scope=spfile;
shutdown immediate;
startup;
闪回数据库
闪回数据库需要闪回日志和重做日志,效果等同于不完全恢复,但是速度相比不完全恢复要快,尤其是在大型数据库中。如果之前做了truncate table这种操作,则不建议闪回数据库,可能会要求大量的归档日志(268页)
原理:利用闪回日志回滚至某个时间点,再从这个时间点开始应用重做日志前滚到目标时间点。
# 设置数据库保留两天的闪回日志
alter system set db_flashback_retention_target=2880;
# 检查闪回日志启用状态
select flashback_on from v$database;
# 启用闪回日志(在快速恢复去的flashback子目录下会出现.flb的文件,这就是闪回日志)
alter database flashback on;
# 再次检查闪回日志启用状态
select flashback_on from v$database;
# 检查最远可以回到哪个时间点或SCN
select oldest_flashback_scn,to_char(oldest_flashback_time,'YYYY-MM-DD HH24:MI:SS')
FROM V$FLASHBACK_DATABASE_LOG;
# 闪回数据库(检查数据情况,如果不是理想恢复点,可以重新设置一个scn反复执行以下操作)
startup mount;
flashback database to scn xxx;
flashback database to timestamp xxx;
alter database open read only;
# 得到满意的恢复点后以resetlogs方式打开数据库
alter database open resetlogs;
总结:
- 闪回查询、闪回事务查询用来观察过去数据
- 闪回数据归档用来扩充闪回查询的时间窗口
- 闪回表、闪回删表以表为单位回到过去
- 闪回事务以十五为单位回到过去
- 闪回数据库以整个数据库为单位回到过去
依赖的功能:
- 闪回事务查询功能:最小补充日志
- 闪回事务功能:主键补充日志
- 闪回数据库功能:快速恢复区、闪回日志