第5章Oracle 10g的闪回机制
5.1 简介
在Oracle中,对于提交的变化,是没有办法回退的。所以这时候就可能存在这样一种情况,对于表做了DML操作,并且在提交后才发现,对表的操作是错误的,此时我们没有办法把提交的错误数据回滚到初始的正确状态;同时,和可能存在一种情况,错误的对表执行了drop操作,由于DDL语句在执行后隐含的含有提交操作,所以这种情况也没有办法把执行了的错误DROP操作回滚的DROP语句执行前的状态。
对于第一种情况,在Oracle 9i版本若发现及时,可以通过dbms_flashback闪回 ,获取到执行错误操作前的数据,然后来执行修复。但是,由于回滚段中的数据可能被覆盖掉,所以通过这种闪回就有个限制。
对于第二种情况,在Oracle 10g以前的各个版本,只能执行数据库的不完整修复才能消除引入的错误操作(DROP TABLE).
下面介绍ORACLE 10G引入的闪回,10G引入的闪回更加灵活,提供的功能也更加强大。
10G引入的删除可分为4种:Flashback Database、Flashback Drop、 Flashback Query、Flashback Versions Query、Flashback Transaction Query。
5.2 Flashback drop
在10G以前的版本中,如果误操作DROP了某张表,那么只能采取数据库的不完整修复来做恢复数据库,但10g版本新增的这个特性,提供了一种对误DROP表的修复方式。
l 先做一个简单实验的例子:
先创建表 create table t( a varchar2(30));
模拟错误操作 DROP表 drop table t;
此时闪回表 flashback table t to before drop;
闪回表T后,表T从误操作后恢复了,并且可以对表T做常规操作。
l Flashback drop table的原理:
在较早的Oracle版本中,drop表时也会从数据字典中彻底删除对这个表的所有引用,恢复被drop掉的表的唯一方法是执行时间点恢复。
而在10g的Oracle数据库中,drop table命令的实现已经发生变化:指定的表不再被删除,而是被重命名。
下面用个例子来说明:
新建一个用户,授予必要的权限,本章的例子都在用户fox完成。
create user fox identified by sys default tablespace users;
create user fox identified by sys default tablespace users;
grant create session ,create table,flashback any table ,debug connect session ,create type,create view,create sequence to fox;
alter user fox quota unlimited on users;
以fox用户建测试表并插入一条记录,
Create table test(a varchar2(4000));
Insert into test(a) values(‘测试flashback drop table’);
Commit;
此时模拟误操作,drop表test:
Drop table test;
由于此用户目前只是创建了一个对象TEST,但是已经被drop掉。但是我们查询
SQL> Select count(*) from user_objects;
COUNT(*)
----------
1
还存在一个对象,查询出这个对象
SQL> select object_name from user_objects;
OBJECT_NAME
-------------------------------------------
BIN$6PH8zhiWR7yzokLGBvg49A==$0
现在来确定下。“BIN$6PH8zhiWR7yzokLGBvg49A==$0”是个什么对象。
SQL> select * from "BIN$H+Wwg3weRqSSlBI3UJOKbg==$0";
查询结果是
A
------------------------------------------------------
测试flashback drop table
此实验证实了我们开始drop的表test,实际上并没有被物理删除,只是被系统自动重新命名了。
恢复表
flashback table test to before drop;
l Oracle的“回收站”
参数RECYCLEBIN(值为ON或者OFF) 用来控制是否开启数据库的flashback drop特性。当此参数值设为OFF时,drop table时不会把表放进“回收站”,而是直接drop掉。当此参数值设为ON时,drop table是会把表放进“回收站”,并可以通过flashback drop特性来修复。
下面在以表test为例来说明:
SQL> drop table test;
SQL> select a.object_name, a.original_name
2 from recyclebin a, user_objects b
3 where a.object_name = b.object_name;
OBJECT_NAME ORIGINAL_NAME
------------------------------ ------------------
BIN$/WDtTeRnQ3io2IQh/yZNJA==$0 TEST
SQL> select a from "BIN$/WDtTeRnQ3io2IQh/yZNJA==$0";
A
-----------------------------------------------------
测试flashback drop table
通过查询“回收站”视图,可以知道表TEST在被DROP后,被系统自动重命名为“BIN$/WDtTeRnQ3io2IQh/yZNJA==$0”。
l 管理“回收站”
通过purge来管理清理“回收站”中的内容,。
语法:
PURGE {TABLE
解释:清理“回收站”中指定的表或索引
语法:
PURGE TABLESPACE
解释:清理“回收站”中存储在指定表空间的上的对象(或指定用户的对象)
语法:
PURGE [USER_|DBA_]RECYCLEBIN
解释:清理“回收站”中当前用户或者所有数据库内的对象。
关于回收站的重要视图:
select * from RECYCLEBIN;
select * from dba_recyclebin;
select * from user_recyclebin;
l 从“回收站”Flashback drop时符合先进后出
用一个简单的例子来说明,并介绍flashback drop时直接重命名对象。
SQL> create table tt (a varchar2(300));
表已创建。
SQL> insert into tt(a) values('先被DROP 到回收站');
已创建 1 行。
SQL> commit;
提交完成。
SQL> drop table tt;
表已删除。
SQL> create table tt( b varchar2(200));
表已创建。
SQL> insert into tt (b) values('第2个被drop到回收站 ');
已创建 1 行。
SQL> commit;
提交完成。
SQL> drop table tt;
表已删除。
SQL> flashback table tt to before drop;
闪回完成。
SQL> select * from tt;
B
----------------------------------------------------------------------------
第2个被drop到回收站
SQL> flashback table tt to before drop;
flashback table tt to before drop
*
第 1 行出现错误:
ORA-38312: 原始名称已被现有对象使用
SQL> flashback table tt to before drop rename to new_tt;
闪回完成。
SQL> select * from new_tt;
A
-------------------------------------------------------------------------
先被DROP 到回收站
从上面的例子,简单总结如下:flashback drop在恢复同名的表时,先被drop放到“回收站”的对象最后被恢复;flashback drop时,可以重新命名对象。
l 使用限制,满足下面任何一条,被drop掉的表,都不能被闪回了:
被drop掉的表不能存储在system表空间上;
被drop掉的表不能存储在数据字典管理的表空间上;
被drop掉的表还存储在“回收站”中,没有被purge掉。
5.3 Flashback Query
通过一个简单例子,来了解flashback query的特性
SQL> create table flash_query as
2 select t.object_id,t.object_name
3 from user_objects t;
表已创建。
SQL> select object_id id ,object_name n from flash_query;
ID N
-------------------
52888 BIN$/WDtTeRnQ3io2IQh/yZNJA==$0
52889 NEW_TT
52890 TT
52892 BIN$gQZY1MJ3RPu7SB7n2bqGYA==$0
52893 FLASH_QUERY
SQL> select to_char(sysdate,'yyyymmddhh24miss') s from dual;
s
--------------
20080904220843
SQL> update flash_query set object_name='error';
已更新5行。
SQL> commit;
提交完成。
SQL> select object_id id, object_name n
2 from flash_query as of timestamp to_timestamp('20080904220843', 'yyyymmddhh24miss');
ID N
---------- ------
52888 BIN$/WDtTeRnQ3io2IQh/yZNJA==$0
52889 NEW_TT
52890 TT
52892 BIN$gQZY1MJ3RPu7SB7n2bqGYA==$0
52893 FLASH_QUERY
SQL> update flash_query s
2 set object_name =
3 (select r.n
4 from (select object_id id, object_name n
5 from flash_query as of timestamp to_timestamp('20080904220843', 'yyyymmddhh24miss')) r
6 where r.id = s.object_id ) ;
已更新5行。
SQL> commit;
提交完成。
SQL> select * from flash_query;
OBJECT_ID OBJECT_NAME
-------------------
52888 BIN$/WDtTeRnQ3io2IQh/yZNJA==$0
52889 NEW_TT
52890 TT
52892 BIN$gQZY1MJ3RPu7SB7n2bqGYA==$0
52893 FLASH_QUERY
解释说明:先创建了一张表flash_query,并插入几条测试记录。随后得到表中存储正确数据的最后时间。 然后,模拟错误的DML语句,把object_name列全部更新为“error”,并且此错误的DML语句被提交。接下来利用flashback query来闪回此表的数据到此表中存储正确数据的最后时间,并确认此时间点的数据正确,然后利用flashback query修复错误DML语句造成的错误结果,并确认修复成功。
在本节的最后介绍,Flashback query 的语法:
Select * From table_name As of [timestamp t1|scn s] Where clause。
其中需要注意的是as of子句,可以支持基于timestamp和scn(系统更改号)两种方式的回闪。
5.4 Flashback Versions Query
在本节,仍然会用到5.2节所创建的表,通过下面一个简单的例子说明Flashback Versions Query特性的使用。
SQL> select object_id id,object_name n
from flash_query where object_id='52893';
ID N
---------- -------------------
52893 FLASH_QUERY
SQL> select to_char(sysdate,'yyyymmddhh24miss') t from dual;
t
--------------
20080904230455
SQL> select to_char(sysdate,'yyyymmddhh24miss') t1 from dual;
T1
--------------
20080904230505
SQL> update flash_query set object_name='VERSION 1' where object_id='52893';
已更新 1 行。
SQL> commit;
提交完成。
SQL> update flash_query set object_name='VERSION 2' where object_id='52893';
已更新 1 行。
SQL> commit;
提交完成。
SQL> select to_char(sysdate,'yyyymmddhh24miss') t2 from dual;
T2
--------------
20080904230647
SQL> select object_id id, object_name n
from flash_query versions
between timestamp to_timestamp('20080904230505', 'yyyymmddhh24miss')
and to_timestamp('20080904230647', 'yyyymmddhh24miss')
where object_id = '52893';
ID N
-------------------
52893 VERSION 2
52893 VERSION 1
52893 FLASH_QUERY
解释说明:在本节的例子,在一个时间段内对flash_query表的同一条记录 object_id = '52893'记录做了两次修改,并在每次修改完成后,做了确认提交。最后可以通过基于版本查询的特性,我们可以查看到记录object_id = '52893'修改历史。最后执行的查询语句可以把伪列VERSIONS_XID也检索出来,以标识出来事务处理的事务ID号。
5.5 Flashback Transaction Query
以DBA用户执行下面的查询语句
SELECT * FROM flashback_transaction_query
WHERE table_owner = 'FOX'
AND table_name = 'FLASH_QUERY'
ORDER BY xid;
这条语句的查询结果参见附件:
Flashback Transaction Query 可以作为诊断数据库事务的工具,来审计数据库中所发生的事务。视图 flashback_transaction_query中的列UNDO SQL 字段,提供了在一段时间内,针对某特定的事务,取消该事务所做的修改而应该执行的SQL语句。
5.6 Flashback Database
数据库必须是归档模式,并启用了flashback database,才可使用此特性。所以在使用flashback database特性前,必须要对数据库做必要的设置。
这里仅仅用一个简单的例子说明用法,并且本节的例子必须以DBA用户来完成。
l 配置flashback database
1)确定数据库是否启用了归档模式,通过
Select log_mode from v$database来查看。
如果是非归档模式,则按照如下步骤来做
SQL> conn /as sysdba
已连接。
SQL> shutdown immediate
数据库已经关闭。
已经卸载数据库。
ORACLE 例程已经关闭。
SQL> startup mount;
ORACLE 例程已经启动。
Total System Global Area 289406976 bytes
Fixed Size 1248576 bytes
Variable Size 96469696 bytes
Database Buffers 184549376 bytes
Redo Buffers 7139328 bytes
数据库装载完毕。
SQL> alter database archivelog;
数据库已更改。
SQL> archive log list;
数据库日志模式 存档模式
自动存档 启用
存档终点 USE_DB_RECOVERY_FILE_DEST
最早的联机日志序列 33
下一个存档日志序列 35
当前日志序列 35
SQL> alter database open;
数据库已更改
此时,数据库被打开,并且处于归档模式下运行。
2) 配置闪回区的路径和闪回区空间大小
SQL>Alter System set db_recovery_file_dest
='C:\oracle\product\10.2.0\flash_recovery_area\DOG' scope=both;
系统已更改。
SQL> alter system set db_recovery_file_dest_size=4g scope=both;
系统已更改。
3)为闪回区保留目标设置保存期限
SQL> alter system set db_flashback_retention_target=240;
保留240分钟。
4)干净关闭数据库并启用database flashback
SQL> shutdown immediate;
数据库已经关闭。
已经卸载数据库。
ORACLE 例程已经关闭。
SQL> startup mount;
ORACLE 例程已经启动。
Total System Global Area 289406976 bytes
Fixed Size 1248576 bytes
Variable Size 96469696 bytes
Database Buffers 184549376 bytes
Redo Buffers 7139328 bytes
数据库装载完毕。
SQL> alter database flashback on;
数据库已更改。
SQL>alter database open;
l 使用flashback database
SQL>conn /as sysdba;
SQL>drop user scott cascade;--DROP 掉了scott用户
SQL>conn scott/sys—此时报错
下面我们就用flashback database来恢复用户scott
SQL>conn /as sysdba;
---flashback dabase 时要求数据库必须已经装载,但未打开,
--所以执行下面操作
SQL>shutdown immediate;
SQL>startup mount;
----执行闪回
SQL>flashback database to
timestamp to_timestamp(‘20080905020202’,’yyyymmddhh24miss’);
SQL>alter database open resetlogs;
--相当于执行了不完整修复,
--所以清理联机日志
SQL>conn scott/sys
connected
本例子的说明:本节,首先配置flashback database,然后模拟错误出现,drop掉了scott用户(错误发生的时间大概是20080905日2分钟后)。发现scott用户不能再次连接数据库后,先关闭数据库,在把数据库启动到mount状态下,然后执行flashback database命令。最后打开数据库,此后scott用户恢复成功,可以正常登录数据库。
l 使用限制,在当前错误时间点和要闪回到的正确的过去时间点之间不能发生过以下时间,否则闪回失败.
控制文件没有被重新创建过或者恢复过;
没有被drop掉的表空间;
数据文件没有shrink过。
5.7 闪回机制的总结
下面用个表格对oracle10g的闪回机制做一总结:
闪回级别 |
使用场景 |
采用哪种Flashback |
使用什么来回闪 |
是否影响数据 |
数据库级别 |
Truncate table; Undesired multitable changes made |
Database |
闪回日志 |
TRUE |
表级 |
Drop table |
Drop |
“回收站” |
TRUE |
表级 |
Update with the wrong WHERE clause |
Table |
撤销段数据 |
TRUE |
表级 |
Compare current data with data from the past |
Query |
撤销段数据 |
FALSE |
表级 |
Compare versions of a row |
Version |
撤销段数据 |
FALSE |
事务级别 |
Investigate several historical states of data |
Transaction |
撤销段数据 |
FALSE |
这张表格总结出了,遇到常见的错误后可以采取何种闪回来恢复错误,但是如果遇到的是介质错误,那么只能通过传统的数据库恢复方法来恢复数据库。
对于5.2 、5.3、 5.4三节介绍的闪回机制,可以统一称为flashback table,也是有使用限制的:
1)启用行移动 alter table table_name enable row movement;
2)不能用于闪回系统表、远程表、外部表;
3)不能跨越DDL语句,即闪回期间如果发生了DDL,则闪回失败;
对于数据库开发人员来说,本章介绍的内容中,5.1、 5.2、 5.3、5.4是非常实用的,而且也是在开发过程中经常可以用来解决遇到问题。5.6 在开发环境一般是使用不上的,在这里仅举个例子说明使用方法。