笔者根据播布客袁保华视频整理而成
目录
闪回数据归档功能不是在数据库级别设置的,而是在表级别设置的。
flashback drop and the recycle bin
从回收站闪回的表名和scott用户下表名冲突了,怎么办----rename
闪 回
数据库发展的三个主题:安全性、性能更快、管理起来方便。
我们今天讲的闪回功能就是为了增强数据库的安全性的。
对于闪回,利用的回收站、回退段、日志三种方式来闪回的。
oracle的闪回功能,是数据库恢复技术的一种革新,也是一种进步。使数据恢复的速度更快。
传想对于统的不完全恢复来说,传统的恢复很慢,比如某个表被删了,传统的恢复是恢复的整个数据库,需要拷贝整个备份的数据,再通过整个日志和归档恢复一下,最后才找到删除的表。所以说传统的恢复的时间很长。
出现闪回技术后,闪回比传统的恢复快很多。
闪回恢复可以按照行、对象、事务处理等来做恢复,也就是闪回只恢复遭到破坏的数据,不需要把无关紧要的表也恢复,所以睡会恢复就很快。
闪回记录的是改变的行、改变的对象、和事务,所以恢复起来就更快。对于没有遭到破坏的对象、行就不用恢复。闪回恢复的时间等于制作错误的时间。
传统的恢复,如果用户出现错误,需要用基于时间点的恢复,其步骤很多,需要宕机,如果数据量又很大,那么恢复时间会非常长,需要DBA掌握的知识比较多。
相反,如果用闪回功能,我们就用几个闪回的命令,就可以把数据进行恢复了。
下面来具体看看oracle 10g以后数据库闪回功能:
上图中可以看出,并不是所有的闪回都是改变数据的,有的只是查看过去某一刻的数据状态。当然也有的闪回是改变数据。
闪回数据库利用的是闪回日志实现的。
数据库的闪回有些是针对人为的误操作,有些是针对所有的操作来进行数据的恢复。
数据库的闪回把所有都闪回到了过去的某一时间点,这和不完全恢复性质差不多。利用数据库闪回的结果就是错误的操作和正确的操作都回到过去的时间点了。所以数据库闪回用于重大错误而产生的非孤立数据的更改。
非孤立数据的更改定义:我做的操作不是影响的一个表,而是一批表,这就是非孤立数据。如果对非孤立数据进行误操作了,一个表一个表的改是不可能的,所以要用数据库闪回技术来恢复。
使用闪回数据库功能相当于数据库出现错误时,我们按回退按钮,使之回退到操作之前,这样的恢复就不用备份了。
闪回数据库恢复只能恢复逻辑的错误,比如人为的把表删了,批处理很多张表处理错了,就可以用闪回数据库进行闪回。但是闪回数据库不能恢复介质的损坏,比如表空间的损坏(但是表被drop了是可以通过数据库闪回的,不过这样闪回的话所有的表的数据都提前了);闪回数据库也不能恢复物理的损坏,如磁盘磁头坏了,就不能用数据库闪回恢复,而是只能用备份文件进行不完全恢复。
物理备份恢复的是方法是万能的,它可以恢复人为和介质的损坏。
但闪回恢复不是万能的,它只能恢复逻辑的错误。
闪回数据库只能解决逻辑错误,不能解决物理错误;另外数据库闪回也要先备份。
闪回数据库利用的是闪回日志,闪回日志和一般的日志不一样,闪回日志记录的是事务操作反写的变化,比如我们执行了一条insert 的sql语句,那么一般的redo记录的就是insert 内容,闪回日志记录的delete 这条内容。
闪回数据库可以减少恢复的时间。
闪回日志需要在操作系统上有存储空间来为其存储。
Rvwr是一个恢复写进程,默认是没开启的,它的作用是把闪回日志缓存区的日志写到闪回日志文件里面。
上述flashbackup logs也是循环写的。
开启闪回日志,对数据库是有开销的,这个开销取决于数据库的负载量。如果数据库是大量读操作,开启闪回功能对数据库是没有开销的。如果数据库有大量的写操作,那么开启闪回会严重影响数据性能,当然我们可以屏蔽某些数据的闪回日志。
具体步骤如下:
一、开启数据库归档
1、配置数据库归档的条件:下面这三个参数在10g和11g可以不用配置,因为数据库有默认值。默认数据库启动时,归档进程会自动启动,归档目录默认在闪回区。
2、启用数据库归档模式
注:改控制文件(是一个二进制文件)是由oracle 的server进程来改的,所有要启动到mount状态。
注:V$database的信息是从控制文件里面读取的
二、启用数据库的闪回功能
先看数据库的闪回状态
三、启动闪回写进程fvwr,使之能写闪回日志
比如下面这张图,表示的是闪回日志目录在闪回区里面
上述看到数据库默认设置闪回的时间是一天(1440分钟)。虽然是闪回一天的数据,但是在一天内如果数据被覆盖了,想闪回被覆盖的数据,就闪回不了了,这点要注意。
闪回时间越长,那么就需要更多的空间来存储闪回日志。
可以在rman或者sql里两种方式来闪回,如下:
上述看到可以通过通过timestamp,scn,恢复点三种方式。
Restore point(恢复点):就是我们再做数据库更改前,先做一个恢复点,如上述恢复点取得名字叫b4_load。恢复点的名字取得要有意义。然后对数据库进行操作。假设你做错了,就可以指定恢复点b4_load就行恢复。
上述timestamp的时间可以用to_date函数将数字进行转化成日期。
上述第四步必须用resetlogs打开数据库,原因是数据库闪回之后,数据文件已经被闪回到以前的时刻,但是我们的控制文件、联机日志文件还是失败时刻的,所有必须用resetlogs把联机日志文件和控制文件重置到闪回的时刻点上,这样三大核心文件(数据文件、控制文件、日志文件)检查点一致了,数据库才能打开。
注:在上面第四步时,可以先不要急着用resetlogs方式打开数据库,可以先用read only方式打开数据库,然后去验证是不是闪回到了所需要的时间点,如果不是,可以回去继续执行闪回命令,只到达到所需要的时间点为止,再以resetlogs方式打开数据库。
方案:
用scott的emp表做测试。
conn scott/tiger
假设emp表里面的员工7369的工资是800,我们准备将其工资改为1000。但是我们在做update时做错了,将7369以及其他所有人的工资的工资都改成了1200,这时候数据就乱了。需要恢复。如果用物理备份的方法就要用基于时间点的不完全恢复,今天我们用数据库闪回来实现。如下:
记录一下7369工资为800时候的时间。
小知识:更改数据库时间格式的方法如下:
记录时间后,更改7369工资为1000,但却发出了如下错误的命令,将所有人的工资都改成1200了
现在用数据库闪回方法来恢复:
以只读方式打开数据库进行验证是否是所需要的状态,如果不是在进行闪回:
看到数据都恢复过来了。
现在数据库是只读,只能查看,不能dml操作。
下面在把数据库改成open read write方式,如下:
再次验证数据发现恢复成功了:
下节介绍闪回数据库的管理
当闪回数据库后一定要先以read only检查是否闪回正确,正确后再以resetlog打开数据库。另外,闪回操作和不完全恢复是不能同时使用的,只能使用其中一种方法来恢复数据。
a、数据库文件被删除,不能将数据进行闪回;
b、被脱机的数据文件,不能将数据进行闪回;
c、如果数据文件空间被reduce size了,那么只能闪回到数据文件空间被回收之后的数据,之前的数据闪回不了了;
d、表空间被删除,不能进行闪回;
e、控制文件的结构发生变化了,也不能进行数据库闪回;
f、当恢复区空间不足时,数据库会自动删除闪回日志,这样即使你设置了闪回日志保持时间是一天,也可能不能将数据库闪回到一天之内的时间点。
例子:
上图可以看出每小时(大概是一个小时)内闪回日志的大小。
虽然我们设置了闪回保留时间,但也不能保证在这个保留时间内闪回数据不被覆盖,闪回空间不够了就会自动删除一些闪回日志,从而使得在闪回保留时间内的数据也不能闪回。因此,我们可以用rman设置备份文件的保留策略,也可以用crosscheck检查过期数据,再用delete清除过期备份的数据,从而释放闪回区的空间,以使闪回日志不被覆盖。
在oracle 10 r2之前,只有基于时间和scn的闪回,到了oracle 10g r2之后,又多了一个restore points恢复点的闪回。这个恢复点相当于是scn的别名。把我们数据库闪回到我们恢复点对应的scn号上。
我们要保证恢复区有足够的磁盘空间存储闪回日志,如果闪回日志被删除了,就不能用恢复点闪回了。
上述guarantee关键字是保证恢复区里面的闪回日志在保留时间内不被删除,即使闪回区空间不够了闪回日化也不会删除。
另外,我们创建好一个恢复点以后,再创建另外一个恢复点后,前一个恢复点就自动删除,所以只有一个闪回恢复点。
使用restore point的要求:
1、10g r2之后;
2、必须开启闪回归档日志
3、日志需要放到闪回恢复区里面
具体实验步骤:
1、
恢复点相当于scn的别名,这样就不用记scn号和时间戳了
将emp表7369的工资由800改成900,但是改坏了,然后我们用恢复点restore point的方式闪回。
上述发现改错了,下面用恢复点闪回;
启动Mount状态就是打开控制文件的过程。
下面开始闪回:
以只读的方式打开数据库进行验证
发现数据已经闪回了
然后再把数据库以read write的方式打开
总结:
1、闪回数据库只能修复逻辑数据错误,不能修复物理错误。
2、闪回数据库不能恢复删除的表空间;
3、数据文件被reduced size之前的状态是不能被闪回的,但是reduce size之后的状态是可以闪回的。
4、当我们重建控制文件后,控制文件发生了变化,也不能用闪回数据库方法闪回数据。
闪回查询:查看过去时间点的数据,可以看到从前的版本数据长的什么样子,类似时间机器。实现原理是利用undo进行恢复的。
闪回版本查询:看在选定的两个时间点内行的所有的版本变化和两个时间点所有事务的变化;
闪回表:可以将某个表的数据闪回到以前的时刻,这样对整个数据库的影响比较小;
闪回事务查询:可以查看过去的时间点事务运行的情况。
以上几种查询只是把某个表回到从前,其他表不受影响,这和闪回数据库查询相比,对数据库的数据损失很小。闪回数据库是把所有表都回到过去的状态,包括没有误操作的表也回到过去了。
实现原理是利用undo。DBA要计算分配undo空间容量,以便有足够undo空间扩展。
那么DBA怎么估算undo空间大小呢?
DBA可以先把undo设置为自动扩展,然后在业务周期内通过v$undostat观察undo空间使用情况,最后就可以给undo设置固定大小。
当前事务未结束的时刻,其他事务可以通过回退段查询数据,但是当前事务提交了,那么其他事务就不能从回退段查看到数据了,如果这时想通过回退段查询数据,需要利用闪回查询。
另外, undo_retention是指定undo数据过期时间,如果过期时间没有达到,即使事务结束了,而且已经提交,已经提交的事务还在回退段,可以随时被闪回应用;如果undo_retention这个过期时间达到了,那么新的数据,新的事务就可能覆盖已经提交的数据,这时就不能利用闪回特称查询过期某一时间点的数据了。
另外,undo_retention越大,那么就需要更大的undo空间。
undo_retention缺省是15分钟。假设在15分钟内,事务提交了,且undo_retention过期时间还没有达到,那么新事务数据不会在undo上覆盖未过期的数据,这样就可以用undo闪回所需要的数据。如果undo表空间不够大,undo表空间被用完了,即使undo_retention时间没有达到,只要事务结束了,系统就有可能覆盖没有过期的回退数据,以保证新的事务正常运行。一旦undo数据被覆盖,就不能利用闪回了。所以我们可以设置retention guarantee属性,用来指明undo_retentin设置的时间有效。就可以保证oracle undo未过期的数据在retention指定的时间内不会被覆盖了,就可以使用闪回恢复所需要的数据了。
在数据库中,默认是no guarantee。可以通过dba_tablespaces查看:
上述可以用timestamp或者scn号两种方法来闪回查询,
闪回查询就可以查看过去时间数据的状态,但并没有修改这个数据。
闪回查询是利用多版本一致性来实现闪回查询,其多版本信息是在undo表空间上的。
利用闪回查询恢复数据的例子:
实验步骤:
emp原始状态
记录此时(t1时刻)的scn号:
修改数据
再次记录此时(t2时刻)的scn号:
识别错误,查看t1时刻的数据:
恢复成t1时刻的数据
验证数据改回来了
可以查询一行数据在某个时间段内版本的变化,利用这个功能可以对相应行进行审计。闪回版本查询实现原理也是通过查看undo上的数据。和闪回查询的区别就是闪回版本查询查看的是一个时间段内数据版本的变化,而闪回查询是查看过去一个时间点的数据。
上述versions_xid是伪列,他是个事务号,versions_xid是以提交的事务来记录每次修改数据的版本,每个成功提交的事务都有一个事务号versions_xid。
另外,上图中version between 后面可以用timestamp和scn来闪回版本查询。
闪回版本查询+闪回查询组合:
1、 定位错误
利用oracle闪回版本查询定位这个错误是在哪个版本出现的;
2、 恢复到需要的版本
闪回版本查询例子
实验方案
具体实验步骤:
emp 表原始状态:
查看当前时间:
下面对数据进行多次修改:
上述事务经历了三个版本。
下面用闪回版本查询来看经历的这些事务版本:
minvale是最早的时间
上述图中的versions_xid,versions_starttime,versions_endtime都是emp表中的伪列。
小知识:
笔者再执行闪回版本查询时遭遇如下错误:
SQL> select versions_xid,versions_starttime,versions_endtime,empno,sal from emp
2 versions between timestamp
to_timestamp('2014-12-16 21:44:22','yyyy-mm-dd hh24:mi:ss') and to_timestamp('2014-12-16 21:50:22','yyyy-mm-dd hh24:mi:ss');ss');
select versions_xid,versions_starttime,versions_endtime,empno,sal from emp
*
ERROR at line 1:
ORA-30052: invalid lower limit snapshot expression
经过百度得知,这个是由于笔者设置的undo_retention=900,而笔者再执行上述闪回版本查询时已经超过900s了,undo的数据过期了。解决办法就是增大undo_retention的值,以使undo里面的数据能长时间存在。
然后我们就可以用闪回查询+DML来进行恢复:
1、 如果是外部表,不能用versions 子查询进行闪回版本;
2、 对临时表不能使用versions子句查看过去某时间的数据版本;
3、 对动态性能视图也不能使用versions子句查询
4、 versions子句也不能使用在视图上
5、 使用versions子句不能跨越DDL操作 。比如我在做ddm后又做了ddl操作,那么ddl操作之前的不能用versions子句查询过去事务版本了,但是可以用versions查询ddl之后的事务版本。
6、 如果我们先对表做insert 操作,后来发现错了,又做了delete操作,那么段中就有就有空洞了,可以用shrink命令回收这些空洞空间。
当我们用shrink命令后,也可以用versions看到过去事务的版本号,但是会看到有些诡异的地方,这就是由于数据库为了使数据块中的数据和原来一样,使数据块中的数据弄得有点诡异。
实验方案:
记录一下此时的时间:
做修改操作:
这时候,事务有了三个版本。
下面通过闪回版本查询:
看到闪回版本查询不能用在视图上。
实验方案
dml操作
ddl(建个约束)操作
再做dml操作:
‘
下面做闪回版本查询:
因为我们用ddl语句改变了表的结构了,就不能用闪回事务查询了。
下面我们把闪回版本时间改到ddl操作之后,这样就能使用闪回版本查询了:
功能:
1、 可以把一个表恢复到以前的时刻
2、 和闪回查询以及闪回版本查询的区别:如果想恢复一个表的子集的数据,用闪回表恢复很方便。而闪回查询和闪回版本查询只对针对一个表的某几行做恢复,而对一个表的子集做恢复就不好实现了
3、 闪回表只对错误的表恢复到以前的时刻,其他表不受影响;
4、 物理的不完全恢复是需要停数据库的,而闪回表恢复不需要起停数据库。
5、 基于时间点的物理不完全恢复、闪回数据库都是把数据库所有的表都回到以前的状态了。而闪回表只针对单个表,其他表不受影响
6、 闪回版本查询和闪回查询是定位时刻点状态的,然后结合dml语句做恢复;而闪回表是直接做闪回操作了。
7、 闪回表实现的原理也是使用undo的数据进行闪回。
8、 使用闪回表功能在闪回一个表的同时也会自动维护索引、触发器、约束,即索引触发器、约束也跟着表一起闪回。一句话,闪回表会自动维护表上的对象(索引、触发器、约束)。
9、 一个用户要有对表的flashback table、select、insert、delete、alter的权限,才能对该表使用闪回表的功能
10、 要启用行移动,才能使用闪回表的功能。因为闪回表会牵涉到块里面行的移动。
启用行移动的方法:
闪回表的命令:
我们可以先用闪回版本查询,查看在某个时间段内经历了哪些事务,然后在用闪回查询,看某个时刻是否是我们需要闪回需要的数据,如果这个时间点正是我们想要的数据,那就可以在该时间段使用闪回表功能闪回数据了。
1、 闪回表不能用在系统表上,即不能用在系统sys用户下或者系统表空间的表。
所以我们再设计业务数据的时候不要把表放在系统用户下或者系统表空间中。
刚才说sys 用户下的数据是不能用闪回表功能的,但是我们在普通用户下,即使在普通用户下把表建立到系统表空间上了,也可以利用闪回表的功能对数据进行闪回,一句话,普通用户下建立的所有表都可以利用闪回表功能的。
2、 闪回表操作不能跨越DDL,不能闪回到DDL(如alter、truncate)操作之前,只能闪回到DDL之后的操作;
有两个例外,如果对一个表做了create index的ddl操作,是可以通过闪回表的功能闪回到create index 操作之前的状态的,并且闪回后新的索引还存在。
同样,如果在一个表上建立了触发器,那么可以通过闪回表功能闪回到建立触发器(ddl操作)之前的状态,并且闪回后该触发器还生效可用。
1、不能使用系统表做闪回的例子
conn / as sysdba
create table emp
as select * from scott.emp;
SQL> select empno,sal from emp where empno=7369;
EMPNO SAL
---------- ----------
7369 900
记录一下时间:
然后我们对sys用户emp 7369的工资改成1000,但是改成了1900
.
定位错误:可以用闪回版本查询定位错误(这里略):
然后利用闪回表的功能做恢复:
上述可以看到sys用户下的表是不能用闪回表功能闪回的。
下面我们在sys用户下,在普通表空间上建立一张表,测试是否可以闪回:
可见,在sys用户下的表,无论是建立在系统表空间或者其他表空间,都是不支持闪回表功能的。
下面我们在普通用户下,把表建立在系统表空间里面:
构造错误:
利用闪回版本查询定位错误:
minvalue最早的时间,maxvalue最后的时间。
用闪回表功能闪回:
结论:sys 用户下的数据是不能用闪回表功能的,但是我们用普通用户下建立表,即使在普通用户下把表建立到系统表空间上了,也可以利用闪回表的功能对数据进行闪回。
2、 闪回表不能跨DDL的例子
做个ddl操作
在做DML操作
下面闪回到ddl操作之前的状态,发现闪回不了:
下面测试闪回到ddl操作之后的状态,发现可以闪回了
3 ddl操作是trigger时对闪回表功能的影响—没有影响
看触发器的信息:
闪回成功了
闪回完成后,触发器还存在并且可用
闪回事务查询功能是定位错误的,类似于闪回版本查询。
今天,我们介绍的闪回事务查询,可以看到数据过去某一时间段数据的事务的变化,也就是说能看这个事务影响的所有行和表的数据变迁。
闪回事务查询+dml操作来做恢复。
闪回事务查询和其他的区别:
闪回查询是查过去一个时间点事务状态的,闪回版本查询是查看过去一个时间段内事务变化的。
闪回表是做恢复的,闪回表可以把一张表上数据恢复到以前状态,但是和这张表关联的其他表的数据状态不能恢复到以前状态;
闪回版本查询,能找到一张表里某些行上数据的变化,但是不能看到和这行数据相关的其他行或表的变化。而闪回事务查询可以看和这行数据相关的其他行或表的变化
闪回事务查询需要查看数据字典flashback_transaction_query。普通用户需要授权才能查看该字典,如下:
select * from session_privs;
desc flashback_transaction_query;
该字典会自动生产undo sql语句进行恢复
我们首先创建两张表,然后对这两张表修改数据,最后用闪回事务查询来恢复两张表关联的数据。
修改数据:
上面commit后,这个是第一个事务
不要commit
上面是第二个事务。
现在准备恢复,先用闪回版本查询看一下这行数据的变迁:
记录上述的xid,此xid会在闪回事务查询里面引用。
再用闪回事务查询一下:
通过上述语句看到了xid=’’的事务里面对应的SQL语句
用上述这个事务里面的相反的SQL语句进行恢复操作:
commit
验证恢复到以前的时刻:
50号部门数据也没有了,说明恢复到了以前的时刻:
闪回事务查询的限制:
只能看DML的语句,ddl语句是查不到的;
############################
在oracle 11g中,对闪回事务查询增加了新特性,可以把独立的事务(独立的事务是指这个事务和其他事务没有关联)撤销掉,就相当于这个事务没发生过一样,但闪回事务查询对有关联的事务撤销就很麻烦。不过,闪回事务就很好的解决了这个问题。
闪回事务功能:可以撤销独立的事务和相互关联的事务(比如我把dept 表20部门删除,那么emp表20部门数据就会受影响,这样就是相关联的事务)。
1、 撤销事务的用户需要拥有如下权限:
2、 要开启附加日志的功能,这样才能在日志中记录额外的信息(比如某个表的主键信息的变化,这就是额外信息)。
3、 闪回事务也会利用undo表空间
通过上述看出,闪回事务很类似oracle的日志挖掘。
4、 闪回事务调用dbms_flashback.transaction_backout这个包里面的过程来进行事务撤销,注意如果加nocasecade选项,表示撤销的是一个独立的事务,和其他事务没有关联,这个事务的撤销对别的事务的数据没有影响。
5、 授予普通用户使用dbms_flashback的权限:
6、 数据库必须是11g才能用闪回事务
1、 通过闪回事务查询来看这个时间段内经历了几个事务
2、 选择有问题的事务
3、 对有问题的独立事务进行撤销
4、 如果是对有关联的事务进行撤销,需要加一下参数来实现
5、可以通过dba_flashback_txn_state 和dba_flashback_txn_report这两个视图看事务之间的依赖关系。
实验方案:
开启附加日志功能,为了使附加日志记录的内容最少,我们可以只开启附加日志记录主键的信息,如下:
授予普通用户对dbms_flashback包有执行权限:
grant select any transaction to scott;
下面构建两个事务
上面是第一个事务
上面是第二个事务
上面的事务1和事务2是没有关联的。
下面通过闪回事务查询,看刚才做了哪些事务:
上面通过闪回事务查询定位到了两个事务。其实我们可以直接通过上述undo_sql语句进行回退,但是如果语句比较多,就比较麻烦。
下面我们通过闪回事务功能回退第二个事务,其实现原理利用的包是dbms_flashback;
下面的pl/sql必须在sys用户下执行,否则会报错。
验证,看到事务2被回撤了。
如果回退的不对,可以用rollback取消刚才的回退,回退正确了再提交commt。
记得commit;
下面回撤事务1
上面我们做了一个独立事务的回退
下面我们再做一个通过闪回事务的方法,回退有关联的事务的一个实验。
实验方案
建立事务1:
我们知道,dept是主键表,emp表是外键表:
建立事务2:
通过闪回事务查询看在这个时间段内有多少个事务:
因为事务2(有外键)依赖事务1(有主键),那么我们现在撤销事务1,会成功吗:
看到我们撤销事务1时出错了,原因是事务2依赖于事务1.
下面我们加个级联的选项来撤销,本应该能成功,但是却失败了,这个可能是oracle的bug:
下面我们再加个选项,只撤销没有冲突的,结果也没有成功:
下面我们在加强制运行回退操作,也没有成功:
看来,我们想一起撤销两个关联的事务,无论加什么参数都是做不到的。
那么怎么办呢?
通过下面的方法来实现。
下面我们先撤销事务2,再撤销事务1就能成功,这样事务2 就不再依赖事务1了:
先撤销事务2:
记得commit:
再撤销事务1,执行成功了:
验证:
commit提交
结论:如果两个事务有主外键关系,那么可以先撤销事务2,再撤销事务1,一步一步来撤销。
闪回数据归档功能:可以查看历史数据,可以对过去的数据进行查询。比如我们数据库有一个重要的表emp,我们想把对emp每次做的修改操作记录都跟踪下来,比如跟踪每个值是什么时候改的,改的是什么等。这个需求我们可以用应用程序的方式来实现,我们可以建立一张历史表,这个历史表和emp表结构一样,不过需要对这个历史表再加个时间的字段,当我对emp表更新记录时,我们通过触发器将emp表的更新变化记录到历史表。如果emp表增加了字段,那么我们还需要在历史表再加个字段,这样维护很麻烦。另外,历史表删除了,那么触发器再运行的时候就会出错。
今天我们讲的闪回数据归档,实现起来就很简单了。
我们以前讲的闪回查询,闪回版本查询,闪回事务查询,他们都是依赖于回退段,所以闪回的时间不会太久。
而闪回数据归档是存放在数据库的表空间中,只有归档不删除,这样就可以闪回很久以前的数据了。
闪回数据归档(11g新特性):数据库会自动跟踪数据库的变化,并写入闪回归档区域里面,这样我们就可以把数据闪回到任何时刻了(不受时间限制)。
如果我们把所有表的变化都放在闪回数据归档区,那么需要的空间是很大的,但数据库允许我们在表的级别设置,只记录哪些表的数据归档。默认的是数据库没有启用闪回数据归档区。
我们可以设置闪回数据归档区里的数据保留时间,以释放空间。
如果我们想对原表加一列,那么闪回归档区为了维护致性,会阻止对原表加入列。
利用闪回数据归档功能,可以对数据进行恢复和审计。
使用闪回数据归档的方法:
进程名:闪回数据归档后台进程
闪回数据归档后台进程的作用,是把数据库数据变化写到闪回数据归档区FDA中,这种写入方式是异步的,缺省是每5分钟写一次。这个进程是把表上数据的变化以压缩的方式写入闪回数据归档区。
另外闪回数据归档区是以天进行分区的,这样让写入I/O尽量低。
此外,当闪回数据归档后台进程空间不够时,数据库是以1M的方式给闪回数据归档区来增加空间的。
上图中,当闪回数据归档后台进程发生将表数据dml操作的变化写到闪回数据归档区的时候,该进程会先把data buffer cache里面的数据变化写入数据闪回区。当脏数据不在buffer cache,而是写数据文件中时,闪回数据归档后台进程就会把undo 里的data写入到闪回数据归档区。
闪回数据归档后台进程也可以监控闪回数据归档区的空间,如果闪回归档区里面有文件过期了,就会删除。
传统的归档文件是存放在操作中的,而闪回数据归档是存放在普通表空间中的
其实就两大步:
第一步:建立闪回归档区的空间
第二步:授权
1、用户权限:
grant select any transection to scott;
grant execute on dbms_flashback to scott;
把用户的表的历史数据放在闪回数据归档区里面:flashback archive
alter table emp flashback archive fda1;
2 系统权限:
flashback archive administrator,这个权限是创建和关联闪回数据归档区的权限。
建立闪回归档区
在一个数据库中是可以有多个闪回数据归档区的。下图中的default表示的是,当我们在给一个表没指明闪回归档区时,默认就是default指定的fla1闪回数据归档区
开启表的闪回归档功能:
下面没有指名闪回数据归档区的名字,就用上面指定默认的fla1。
通过闪回数据归档查看历史数据
也可以使用闪回数据归档来看闪回数据版本查询
1、 创建存放数据归档区的表空间
2、 建立数据闪回归档管理员并授权
下面授予该用户归档管理权限,该权限表示可以创建闪回数据归档区
再给connnet和resource的角色
查看自己有哪些权限:
connfbda_admin/fbda_admin
3、 创建一个普通用户,做为数据归档区的使用者
4、 创建闪回数据归档区
创建几个都行
5、 授权普通用户可以使用哪个闪回数据区
6、 使用:
产生事务1:
产生事务2:
7、 使用闪回版本查询,其数据来自undo
如果undo被覆盖,那么执行上述语句就会报错。下面我们就一起来测试一下:
8、 建立一个undotbs2,,并删除原来的undotbs1---注意,以下几步纯是测试用的,生产中不要用。
9、
10、
看到出现了01555错误,因为闪回版本查询的数据来自undo,我们把以前的undotbs1删除了,所以就报了01555的错误。
11、 利用闪回数据归档来查看历史数据
11.1 启用表emp的闪回数据归档功能
启用该功能,就会把修改emp表的历史数据全都放在闪回数据归档区里面。
11.2 模拟数据丢失
事务1:
事务2:
11.3再用闪回版本查询的数据就不是来自undo,而是来自闪回数据归档区了。
11.4 测试:再次删除undotbs2,目的是用来确认闪回版本查询的数据来自闪回数据归档区,而不是unotbs2
再执行闪回版本查询,发现数据被查出来了,说明数据来源于闪回数据归档区:
小知识:
闪回数据归档后台进程会把data buffer cache和undo里面的数据写到闪回数据归档区里面。
上述没有写闪回数据归档区的名称,表示用的是默认的闪回数据归档区。
使用闪回数据归档区
闪回查询
或者闪回版本查询使用闪回数据归档区
对闪回数据归档区添加空间
手工删除闪回数据归档区的数据
当然清除闪回归档区的数据也可以自动删除,即根据设置的保留期限来自动闪回。
删除闪回数据归档区
用闪回数据归档的管理员登陆:
flashback_archive# 表示的是闪回数据归档区名字的编号。
查看闪回数据归档的表空间的信息
conn test/test
上述增加的表就是历史表。
emp和 sys_fba_hist_74981表结构几乎一样,sys_fba_hist_74981是emp表的历史表。当emp表发生变化时,其数据变化就会自动写入到历史表sys_fba_hist_74981
下面这个表user_flashback_archive_tables列出哪些表启用了闪回数据归档功能,以及其对应的历史表是什么,这些历史表都在闪回数据归档区里面:
闪回数据归档功能可以跨越DDL操作
我们前面讲的基于undo的闪回版本查询是不能跨DDL操作的,但是我们现在要讲的闪回数据归档功能是可以跨DDL操作的。
下面我们就做个实验,来验证闪回数据归档可以跨越ddl。
对emp表做个DDL操作:
跨越ddl操作后,基于闪回数据归档的闪回版本查询还可以用(以前基于undo的闪回版本查询如果跨越ddl操作会报错):
在oracle 11g r2中,使用闪回数据归档功能,如果对原表增加列,删除列,列重新命名,列的长度更改了,或者表的一个分区truncate了,再或者整个表truncate或改名了,那么闪回数据归档的历史表也会做相应的操作,从而使原表和历史表保持一致。但是在11 r2之前,不支持上述功能。
闪回数据归档功能也有不支持的ddl操作:drop这时候可以用dbms_flashback_archive包,来使原表和历史表取消关联,这样就可以对原表做类似drop等的ddl操作。然后在用dbms_flashback_archive把原表和历史表做关联。
下面这张图很好的诠释了在一张表删除一列数据和增加一列数据,那么历史表也做相应的操作。
实验:
启用表的闪回数据归档功能
对表执行一个ddl操作:
执行这个操作后,t表的历史表也会自动删除object_id列。
desc sys_fba_hist_75030 ; --可以看到t表的历史表sys_fba_hist_75030也删除相应的列。
下面我们在测试drop 命令
看到t表不能删除,原因是闪回数据归档不支持drop命令
发现历史表也不能删除:
如果想把一个表的数据分出来,或者把两个分区的数据做一个交换,这时候可以用dbms_flashback_archive包,这个包里面有些过程,来使原表和历史表取消关联,这样就可以对原表做类似drop等的ddl操作。然后在用dbms_flashback_archive把原表和历史表做关联。使用这个表的前提是:基表(原始表如emp)和历史表必须在同一个用户下。如下图:
我们建立一张和历史表一样的表t2,用来备份这个历史表:
下面我们解除基表t和历史表的关联
然后我们再用ddl命令drop来删除历史表,这时候就可以删除了:
看到现在可以删除了,因为我们解除了基表t和历史表的关联了,所以就可以删除了。
现在我们再用dbms_flashback_archive包将基表t和它的历史表来做关联,我们发现现在关联不上了,原因是我们把t表的历史表给删除了。但是我们留了一手,我们在上步给历史表做了个备份t2。
我们把历史表的备份表t2改名成原来历史表的名字:
再次建立基表和历史表的关联,看到成功了:
现在我们再把历史表删除,看到又是不允许的,因为基表和历史表已经做了关联,恢复到以前的关联关系了:
上述过程可以用下图表示:
利用闪回数据归档,可以利用oracle闪回查询(查的是过去的时间点)和闪回版本查询(过去时间段的查询)来查过去的数据;同时,不管是闪回查询还是闪回版面查询,都可以用scn或者时间戳来查询。
有时我们查询过去的数据时,发现在一秒钟和两秒中的数据是一样的,原因是oracle是以事务为单位进行查询的,所以时间段内数据是一样的。
闪回数据归档功能不是在数据库级别设置的,而是在表级别设置的。
如果不小心把一张表删除了,可以通过oracle回收站的功能,把删除的表闪回。
回收站的功能是否开启,通过recyclebin=on设置。
oracle的数据字典记录了回收站的信息。当我们删除了一张表,其实并没有真的开辟一块空间当做回收站,来把删除的表放到里面,而是删除的表占用的还是原来的空间。只是把删除表的信息记录在了数据字典(dba_free_space)中,同时把删除的表名在回收站中重命名了。
1、 自动释放 当我们把表删除后,在回收站中会把该表重新命名。但数据字典dba_free_space会把重新命名的
当成空闲(free)空间。
oracle会优先使用没有用过的崭新的空闲空间,当这样的崭新的空闲空间用完后,oracle才会使用回收站中所标记对象的空闲空间的,当回收站的空间也用完了,如果表空间是自动扩展的,那么这个表空间就会autoextend 来扩展空间。
2、 手工释放
用命令purge user_recyclebin(只清除当前用户自己回收站的数据)或者purge dba_recyclebin(把数据库中所有的回收站的信息清除掉),将空间也被释放。
用如下命令清除回收站中某个表:
用如下命令清除回收站中表空间里的某个用户的回收站的信息:
用如下命令表示再删表时,把该表回收站的信息也删除,这回表的空间释放了:
在删除表空间时,加including contents表示把表空间中对象的回收站信息也清除:
删除用户时,加cascade,表示把用户对象回收站的信息也清除掉:
下图表示再做drop操作时,不会放在回收站里面:
*.当我们在drop表的时候,表上的索引也同时被drop掉了。
flash drop的实验:
上图看到,表并没有真正的删除,只是rename了一下。
可以通过show recyclebin看回收站的内容,也可以通过字典user_recyclebin(用这个能看删除的索引信息)来看:
当我们用闪回技术闪回到drop前的状态,那么闪回回来的表上索引的名字,约束的名字、触发器的名字还会保留回收站中的名字。这时候我们可以通过rename命令进行重命名。
假如我们把emp表删除后放进回收站了,但我们又删除了一个也叫emp的表,那么我们在从回收站恢复emp表时,闪回的是哪个表呢?其实利用后进先出的原则来恢复回收站的表的。下面我们做实验来验证后进先出的原则
实验:
此时员工7369工资是800
我们再创建一张emp1的表
此时7369的工资是900
看到回收站中emp1后两个版本。
我们再创建一个emp1的表:
此时7369的工资是1000
再删除emp1
这时候我们看到回收站里面emp1有三个版本,我们再恢复的时候,是按照后进先出的原则来恢复。
我们的emp1第一个版本员工7369工资是800,第二个版本7369工资是900,第三个版本是1000;
看到恢复的数据版本是第三个版本,7369的工资是1000时的emp1表。从而证明了后进先出的原则。
清除回收站,其表占据的空间也被清空了。
如果是dba,可以purge dba_recyclebin;这样清空的是数据库所有用户的的回收站。
清空后,看到select * from tab显示的干净了,不再有
这样的表了。
我们可以这样做个试验:在回收站中的emp1表的7369工资是1000,而scott用户下的emp1表emp1 7369工资是800,在这种情况下,从回收站进行闪回,会怎么样呢?
上面闪回看到报错了。
可以通过rename来解决:
完。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/28916011/viewspace-1392663/ ,如需转载,请注明出处,否则将追究法律责任。