Chinaunix首页 | 论坛 | 博客
  • 博客访问: 244828
  • 博文数量: 64
  • 博客积分: 1416
  • 博客等级: 上尉
  • 技术积分: 565
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-18 10:54
文章分类

全部博文(64)

文章存档

2011年(4)

2010年(60)

我的朋友

分类: Oracle

2010-03-30 21:06:26

一 Flashback database

falshback database是采用日志
falsgback drop是采用表空间的空间
其它的都是与undo有关。。。

fashback是我对10g一直比较感兴趣的东西,现在,我决定将其系统的整理出来,在以后的时间里,我将每天推出一个新的flashback的功能(不包括周末

Oracle 10g的flashback有了强劲的改进,从普通的falshback query发展到了多种形式,主要表现在如下几个主要方面。通过Oracle 10g,你甚至可以不需要从备份恢复,完成恢复工作。
1、Oracle Flashback Database
这个特性允许你通过SQL语句FLASHBACK DATABSE语句,让数据库前滚到当前的前一个时间点或者SCN,而不需要做时间点的恢复。
2、Oracle Flashback Table
这个特性允许你利用SQL语句FLASHBACK TABLE语句,确保回滚到表的前一个时间点。
3、Oracle Flashback Drop
Oracle 10g开始提供一个类似垃圾站的功能,来恢复不小心被drop的表
4、Oracle Flashback Version Query
利用保存的回滚信息,你可以看到特定的表在时间段内的任何修改,如电影的回放一样,你将了解表在该期间的任何变化
5、Oracle Flashback Transaction Query
这个特性将确保您检查数据库的任何改变在一个事务级别。你可以利用它来诊断问题,性能分析和审计事务

正好是一周的时间。。。。。

由于时间仓促,难免错误多多,欢迎大家讨论并提宝贵意见

闪回数据库可以迅速的时数据库回到误操作或人为错误的前一个时间点,如实际中的“撤消”操作,将可以不利用备份就快速的实现时间点的恢复(有后悔药可以吃了)。实际上,Oracle为了实现这一个功能,创建了另外一组日志,就是Flashback Logs(前滚日志),记录数据库的前滚操作。如果希望能闪回数据库,需要设置如下参数:
DB_RECOVER_FILE_DEST
DB_RECOVER_FILE_DEST_SIZE
这两个参数来确定Flashback日志的存放地点与该恢复区的大小。在创建数据库的时候,Oracle将自动创建恢复区(需要注意,该恢复区可不仅仅是 为了flashback log,还可以用来归档,备份与恢复),但是默认是关闭Flashback database功能。如果想要利用这一功能,DBA就必须正确的配置该日志区的大小,如一个数据库的数据库,每天有10%的块发生改变,那么一天(24 小时)的Flash Recovery Area就是1/10个数据库大小。DBA也可以动态的改变其大小以满足不同的需求。
另外一个参数DB_FLASHBACK_RETENTION_TARGET参数允许您设定闪回数据的保存时间,单位是分。默认是一天(24*60)
如果想启动FLASHBACK DATABASE的功能,您必须在MOUNT模式下,执行alter database flashback on命令。或者是alter tablespace tsname flashback on,数据库将采集falshback log,如果需要关系该功能,则修改On为OFF。
如果想执行flashback database命令,你可以在两种方式下执行:RMAN与SQLPLUS。
SQL >flashback database to time to_date(xxx);
SQL >flashback database to time TO_TIMESTAMP (xxx);
SQL >flashback database to scn xxx
SQL >flashback database to sequence xxx thread 1
SQL>flashback database to timestamp(sysdate-1/24)
我们下面看看具体的例子说明
SQL> startup mount
ORACLE instance started.
Total System Global Area  113246208 bytes
Fixed Size                   787708 bytes
Variable Size              87030532 bytes
Database Buffers           25165824 bytes
Redo Buffers                 262144 bytes
Database mounted.
SQL> alter database flashback on;
alter database flashback on
*
ERROR at line 1:
ORA-38706: Cannot turn on FLASHBACK DATABASE logging.
ORA-38707: Media recovery is not enabled.
可以看到,flashback还必须要归档的保证
SQL> alter database archivelog;
Database altered.
SQL> alter database flashback on;
Database altered.
SQL> alter database open;
Database altered.
SQL> archive log list
Database log mode              Archive Mode
Automatic archival             Enabled
Archive destination            USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence     13
Next log sequence to archive   15
Current log sequence           15
经过以上步骤,我们确保了flashback database的功能,我们还可以发现,10g的自动归档是不需要手工干预的,只要开启了归档,就是自动归档了,归档区也在DB_RECOVERY_FILE_DEST参数指定的地点。

通过如下的查询
SQL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';
Session altered.
SQL> SELECT OLDEST_FLASHBACK_SCN, OLDEST_FLASHBACK_TIME
  2        FROM V$FLASHBACK_DATABASE_LOG;

OLDEST_FLASHBACK_SCN OLDEST_FLASHBACK_TI
-------------------- -------------------
             1135440 2004-04-06 15:20:57
我们可以知道,可以前滚恢复到的最早的SCN与时间点是多少,如果没有确保flashback database,该视图将没有查询结果。

我们创建三个一样的表
SQL> create table t1 as select * from dba_objects;
Table created.
SQL> create table t2 as select * from t1;
Table created.
SQL> create table t3 as select * from t1;
Table created.
SQL> set time on;
SQL> select sysdate from dual;
SYSDATE
-------------------
2004-04-06 15:29:33
我们确定了一个时间点
现在,我们分别truncate一个表与drop一个表,模拟误操作。
15:30:10 SQL> truncate table t2;
Table truncated.
15:30:43 SQL> drop table t3;
Table dropped.
没有备份,我们利用flashback来恢复数据库到2004-04-06 15:29:33时间点。
15:39:02 SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
15:39:31 SQL> startup mount exclusive
ORACLE instance started.
15:41:19 SQL> FLASHBACK DATABASE TO timestamp(to_date('2004-04-06 15:29:33','yyyy-mm-dd hh24:mi:ss'));
Flashback complete.
之后,我们可以用
ALTER DATABASE OPEN READ ONLY来检查结果是否正确,如果满足结果,则可以用resetlog来正式启动数据库,注意,一旦resetlogs之后,将不能再flashback的resetlogs之前的时间点。
15:41:32 SQL> alter database open resetlogs;
Database altered.
我们现在查询那三个表
15:42:10 SQL> select count(*) from t1;
  COUNT(*)
----------
     47708
15:42:47 SQL> select count(*) from t2;
  COUNT(*)
----------
     47708
15:42:50 SQL> select count(*) from t3;
  COUNT(*)
----------
     47708
发现truncate的记录或者是drop的表都存在,现在数据库已经前滚到前一个时间点了。
15:44:56 SQL> SELECT OLDEST_FLASHBACK_SCN, OLDEST_FLASHBACK_TIME
15:45:05   2          FROM V$FLASHBACK_DATABASE_LOG;


OLDEST_FLASHBACK_SCN OLDEST_FLASHBACK_TI
-------------------- -------------------
             1136169 2004-04-06 15:41:50
同时发现数据库的最早的flashback的时间与scn都回到resetlog的时间点了。



二  10g新特性,flashback系列之二 —— flashback table

今天第2天了

发表第二个特性,flashback table

发现很多人怎么把他与flashback drop给弄混了
包括Arup Nanda
写The Top 20 Features for DBAs
我看了他的flashback table ,其实是flashback drop


好了,明天我也介绍flashback drop,今天还是言归正传
flashback table

flashback table与9i的flashback query相似,利用undo信息来恢复一个或者一些表到现在以前的一个时间点(一个快照)。Undo相关参数如下,需要确保AUM与足够的retention值。
SQL> show parameter undo
NAME                                 TYPE        VALUE
------------------------------------ ----------- -----------
undo_management                    string      AUTO
undo_retention                       integer     900
undo_tablespace                      string      UNDOTBS1
首先要说明的是,flashback table不等于flashback query,所谓query,仅仅是查询以前的一个快照点而已,并不改变当前表的状态,而flashback table不一样,将改变当前表及附属对象一起回到以前的时间点。
其实9i的flashback query在10g中也有了新的变化,10g中可以简单的利用以下语句实现flashback query,而不再需要象9i那样需要调用DBMS_FLASHBACK包。
SELECT * FROM TABLENAME  AS OF TIMESTAMP
TO_TIMESTAMP('2003-04-04 09:30:00', 'YYYY-MM-DD HH:MI:SS')
WHERE ……;

10g的flashback table有如下特性
·        在线操作
·        恢复到指定时间点或者SCN的任何数据.
·        自动恢复相关属性,如索引,触发器等
·        满足分布式的一致性
·        满足数据一致性,所有相关对象将自动一致
语法为:
FLASHBACK TABLE tablename TO TIMESTAMP (JUL-07-2003, 02:33:00)
FLASHBACK TABLE employee TO SCN 123456;
FLASHBACK TABLE t1 TO TIMESTAMP '2003-03-03 12:05:00' ENABLE TRIGGERS;
其中ENABLE TRIGGERS表示触发器恢复之后为enable状态,而默认为disable状态。

注意:如果需要flashback一个表,需要保证
需要有flashback any table的系统权限或者是该表的flashback对象权限。
需要有该表的SELECT, INSERT, DELETE, ALTER权限
必须保证该表ROW MOVEMENT

下面,我们用一个详细的例子来说明这个过程:
16:16:51 SQL> create user flash identified by flash;
User created.
16:17:04 SQL> grant connect,resource to flash;
Grant succeeded.
16:17:19 SQL> connect flash/flash;
Connected.
16:26:35 SQL> create table t1 as select * from all_objects;
Table created.
16:37:24 SQL> create table t2 as select * from t1;
Table created.

16:37:35 SQL> select count(*) from t1;
  COUNT(*)
----------
     38949
16:37:43 SQL> select count(*) from t2;
  COUNT(*)
----------
     38949
16:38:06 SQL> create index inx_test1 on T1 (object_name);
Index created.
16:39:55 SQL> create index inx_test2 on T1 (object_id);
Index created.
16:40:47 SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;
TO_CHAR(SYSDATE,'YY
-------------------
2004-04-06 16:41:18
以上获得一个时间戳,假定我们要恢复该表到这个时间,那么以下对该表的操作都将被前滚。
16:41:18 SQL> drop index inx_test1;
Index dropped.
16:41:33 SQL> delete from t1;
38949 rows deleted.
16:41:46 SQL> commit;
Commit complete.
16:41:49 SQL> truncate table t2;
Table truncated.

在以上的操作中,我们delete一个表,然后truncate一个表,下面,我们将来看看flashback table的效果,能恢复到什么程度
16:37:55 SQL> ALTER TABLE t1 ENABLE ROW MOVEMENT;
Table altered.
16:38:03 SQL> ALTER TABLE t2 ENABLE ROW MOVEMENT;
Table altered.

16:43:10 SQL> flashback table t1 TO TIMESTAMP to_timestamp('2004-04-06 16:41:18','yyyy-mm-dd hh24:mi:ss');
Flashback complete.
16:43:49 SQL> flashback table t2 TO TIMESTAMP to_timestamp('2004-04-06 16:41:18','yyyy-mm-dd hh24:mi:ss');
flashback table t2 TO TIMESTAMP to_timestamp('2004-04-06 16:41:18','yyyy-mm-dd hh24:mi:ss')
                *
ERROR at line 1:
ORA-01466: unable to read data - table definition has changed

我们可以发现,执行delete操作的表是可以恢复的,而执行truncate操作的表是不可以恢复的,这正好也说明了flashback table利用undo的结论。
看看我们的结果:
SQL> select count(*) from t1;
  COUNT(*)
----------
     38949
SQL> select count(*) from t2;
  COUNT(*)
----------
         0

SQL> select t.index_name from user_indexes t where t.table_name='T1';
INDEX_NAME
------------------------------
INX_TEST2
还可以看到,对于drop的索引,也是没有办法恢复的,因为drop并不记录undo,所以所谓索引的恢复,仅仅是相关索引树的改变而不能找回删除掉的索引。


三  10g新特性,flashback系列之三 —— flashback drop

flashback drop的文章已经出现的很多了
包括从最初的fenng的
Oracle 10G 中的"回收站"



Arup Nanda 的
Oracle Database 10g: The Top 20 Features for DBAs


但是,既然我要讨论flashback系列,那drop也是必不可少的了。
那么,我就站在这些巨人的肩上,再对falshback drop做一次完整的叙述。


falshback drop其实就是类似win的回收站功能,可以让不小心被drop的对象再被找回来(又有后悔药可以吃了 ),但是仅仅是drop哦,如果是truncate,呵呵,flashback drop帮不了你的忙。。。

flashback drop不是借助于undo,呵呵,这个与falshback database与flashback table都不一样(应当是这三个都不一样)。。。

最后,再悄悄的说一声,不要以为有了回收站,就安全了,有可能回收站中的信息有可能在不知中也被清除了。。。
flashback drop

意外的drop对象时有发生,当用户或者甚至是DBA认识到这个错误的时候,很多时候都太晚了,在以前的版本中,除了不完全恢复,几乎是没有一个好的解决 办法,Oracle 10g的flashback drop功能,允许你恢复一个被删除(drop)了的对象,oracle将自动将该对象放入回收站(但是注意,对于truncate的表,除了 flashback database之外,其它的flashback功能可能帮不了你)。
所谓的回收站,是一个虚拟的容器,用于存放所有被删除的对象。在回收站中,被删除的对象将占用创建时的同样的空间,对于一个对象的删除,其实仅仅就是简单 的重令名操作。你甚至还可以对已经删除的表查询,也可以利用flashback功能来恢复它, 这个就是flashback drop功能。
关于回收站内的相关信息可以从recyclebin/USER_recyclebin/DBA_recyclebin等视图中获取,或者通过SQL*Plus的show recyclebin 命令查看
回收站的对象在如下情况下将被清除:
·由于添加新的对象引起表空间的空间不够或者用户的空间配额不够
·表空间需要扩展新区间来增长空间
·手工发purge命令或flashback命令

现在我们做一个简单的测试
SQL> create user test identified by test;
User created.
SQL> grant connect,resource to test;
Grant succeeded.
SQL> connect test/test;
Connected.
SQL> show recyclebin;

可以看到,回收站中是没有任何结果的,表示没有任何表在回收站中。
现在,我们创建一个表,并drop它
SQL> create table t1 as select * from all_objects;
Table created.
SQL> drop table t1;
Table dropped.
SQL> select table_name from user_tables;
TABLE_NAME
------------------------------
BIN$nwjcjTOtQUirZW4H1wlFVA==$0
SQL> show recyclebin
ORIGINAL NAME    RECYCLEBIN NAME                OBJECT TYPE  DROP TIME
---------------- ------------------------------ ------------ -------------------
T1    BIN$nwjcjTOtQUirZW4H1wlFVA==$0 TABLE        2004-04-07:13:12:56
show resyclebin的信息同样可以从recyclebin/user_recyclebin/dba_recyclebin等视图中获得中获得,而且回收站中的表依然可以在user_tables/dba_tables中查询到。
通过以上查询可以看到,该表被放入了回收站,而且名称也变了,当一个表被删除并移动到"回收站"中,它的名字要进行一些转换.这样的目的显而易见是为了避免同类对象名称的重复,转换后的名字格式如下:
BIN$$globalUID$version
其中的globalUID是一个全局唯一的,24个字符长的标示对象,没有任何实际意义,也不可能从这里看到对象未删除前实际的名称。
$ version is是数据库分配的版本号
回收站中的名称为30个字符
通过如下的语句
SQL> select count(*) from "BIN$nwjcjTOtQUirZW4H1wlFVA==$0";
  COUNT(*)
----------
     38947
可以看到,实际上,该表在回收站中还是可以被访问的,但是不能在上面发布任何DDL/DML语句。
我们通过FLASHBACK TABLE TABLENAME TO BEFORE DROP;
可以将表恢复到删除之前。如
SQL> FLASHBACK TABLE t1 TO BEFORE DROP;
或者
SQL> FLASHBACK TABLE BIN$nwjcjTOtQUirZW4H1wlFVA==$0 TO BEFORE DROP;
Flashback complete.
SQL> show recyclebin

SQL> select table_name from user_tables;
TABLE_NAME
------------------------------
T1
可以看到,表T1已经被恢复了,需要注意的是,flashback命令中的表名可以是原来的名字或者是回收站中的名称,都无所谓。如果原来的名称在回收站中存在同名,那么将恢复最后drop的表。
如,我先删除原来的表t1,就是刚才创建的表
SQL> drop table t1;
Table dropped.
在创建一个同样的表(但是内容不一样)
SQL> create table t1 as select * from dual;
Table created.
SQL> drop table t1;
Table dropped.
SQL> show recyclebin;
ORIGINAL NAME    RECYCLEBIN NAME                OBJECT TYPE  DROP TIME
---------------- ------------------------------ ------------ -------------------
T1   BIN$FXe9sgDgQM69yX5gNR+qtA==$0 TABLE        2004-04-07:13:36:40
T1   BIN$pj80dtOaSwawSKb/rd3Vhg==$0 TABLE        2004-04-07:13:36:17
可以看到,在回收站中现在存在两个表T1,但是drop的时间不一样。
SQL> FLASHBACK TABLE t1 TO BEFORE DROP RENAME TO t1_1;
Flashback complete.
SQL> select count(*) from t1_1;
  COUNT(*)
----------
         1
可以看到恢复的是从dual创建的T1,而不是从all_objects创建的t1,也就是后来创建并drop的表,如果想恢复先删除的表怎么办呢?其实只要在flashback命令后用回收站中的名称恢复就可以了。

怎么管理回收站的信息呢,我们可以用purge table清除单个表或者是purge recyclebin清除整个回收站。
SQL> drop table t1_1;
Table dropped.
SQL> create table t1 as select * from dual;
Table created.
SQL> drop table t1;
Table dropped.
SQL> show recyclebin
ORIGINAL NAME    RECYCLEBIN NAME                OBJECT TYPE  DROP TIME
---------------- ------------------------------ ------------ -------------------
T1     BIN$f0UqwWsqQAaQDo5FYyTM3A==$0 TABLE        2004-04-07:13:46:28
T1     BIN$pj80dtOaSwawSKb/rd3Vhg==$0 TABLE        2004-04-07:13:36:17
T1_1   BIN$MVdYcZOzR/KxaX0HGogz9Q==$0 TABLE        2004-04-07:13:45:41
可以看到,现在有三个对象在回收站中
SQL> purge table t1;
Table purged.
SQL> show recyclebin
ORIGINAL NAME    RECYCLEBIN NAME                OBJECT TYPE  DROP TIME
---------------- ------------------------------ ------------ -------------------
T1               BIN$f0UqwWsqQAaQDo5FYyTM3A==$0 TABLE        2004-04-07:13:46:28
T1_1             BIN$MVdYcZOzR/KxaX0HGogz9Q==$0 TABLE        2004-04-07:13:45:41

可以看到,同样道理,purge tbale t1并不是清除两个已经删除的表t1,而是仅仅是清除随后被删除的表
SQL> purge recyclebin;
Recyclebin purged.
SQL> show recyclebin
之后,可以看到,回收站中已经没有任何信息
同理我们可以通过purge user_recyclebin或者是purge dba_recyclebin来清除不同的回收站对象。也可以通过PURGE TABLESPACE TSNAME,PURGE TABLESPACE TSNAME USER USERNAME命令来选择清除回收站。
如果删除一个表,而不想放到回收站中,可以利用purge选项在drop语句中,如
drop table tablename purge

另外,还有一些需要注意的地方
·drop tablespace tsname including contents时,表空间内的所有对象包括回收站内的对象都将被清除。
·如果仅仅是drop tablespace时,如果有永久对象将不能执行,如果仅仅是有回收站内的对象,将先清除回收站,然后删除表空间
·如果drop user username cascade时,所有对象将被删除,而且不放入回收站


四    10g新特性,flashback系列之四 —— flashback version query

大家周末好,又是星期一了,很不喜欢星期一,还要五天后才是周末

今天说说flashback version query,这个也被讨论过了的一个特性,感觉主要作用就是用来审计以前的一些操作。如不小心删除了表,通过flashback version query就可以知道什么时候执行了删除操作,删除了什么。甚至可以回滚。

好了,我们就来看看flashback version query,这个在一定程度上有点象logmnr与审计的东西。
flashback version query

flashback version query提供了一个审计行改变的功能,它能找到所有已经提交了的行的记录,比如说,时间1,我插入一条记录,时间2我删除了这条记录,对于时间3,当然 查询不到这条记录,但是flashback version query能够把时间1、时间2的操作给记录下来,并详细的查询出来。
flashback version query一样依赖于AUM,所以,这里就不再多说AUM的配置。flashback version query采用VERSIONS BETWEEN语句来进行查询,常用的有
·        VERSIONS_SCN - 系统改变号
·        VERSIONS_TIMESTAMP - 时间
flashback version query是一个功能强大的工具,可以分析到什么时间执行了什么操作的问题。也可以用于记录的审计,而没有必要去开启细粒度审计功能或者是使用LOGMNR了。
下面将展示这个具有电影功能的flashback version query
SQL> connect test/test
Connected.
SQL> create table test(a int,b varchar2(10));
Table created.
我们执行一系列如下的操作
16:33:17 SQL> insert into test values(1,'16:33:17');
1 row created.
16:33:31 SQL> commit;
Commit complete.
16:33:34 SQL> update test set a=2,b='16:33:34';
1 row updated.
16:33:53 SQL> commit;
Commit complete.
16:33:57 SQL> update test set a=3;
1 row updated.
16:34:04 SQL> commit;
Commit complete.
16:34:06 SQL> delete test;
1 row deleted.
16:34:11 SQL> commit;
Commit complete.
16:34:13 SQL> insert into test values(4,'16:34:13');
1 row created.
16:34:32 SQL> commit;
Commit complete.
16:34:34 SQL> update test set a=5,b='16:34:34';
1 row updated.
16:34:46 SQL> commit;
Commit complete.
现在,我们看到该表最后的记录是
16:34:49 SQL> select * from test;
         A B
---------- ----------
         5 16:34:34
这个时候,如果我们利用flash table或者是flash query,我们也只能是看到过去的莫一个快照而已,利用flashback version query,我们将找到其中的任何变化,如
SQL>select versions_starttime, versions_endtime, versions_xid,
      versions_operation, a,b
      from test versions between timestamp minvalue and maxvalue
      order by VERSIONS_STARTTIME;


VERSIONS_STARTTIME VERSIONS_ENDTIME VERSIONS_XID VERSIONS_OPERATION  A B
----------------  ------------- ----------- ----------------  ------ ------
07-APR-04 04.33.33 PM  07-APR-04 04.33.55 PM  0400230098010000 I  1 16:33:17
07-APR-04 04.33.55 PM  07-APR-04 04.34.04 PM  0400270098010000 U  2 16:33:34
07-APR-04 04.34.04 PM  07-APR-04 04.34.13 PM  0400280098010000 U  3 16:33:34
07-APR-04 04.34.13 PM                         0400290098010000 D  3 16:33:34
07-APR-04 04.34.31 PM  07-APR-04 04.34.47 PM  0400260098010000 I  4 16:34:13
07-APR-04 04.34.47 PM                         04000C0099010000 U  5 16:34:34
6 rows selected

注意:
此处显示了对该表所作的所有更改,甚至包括该行被删除和重新插入的情况。VERSION_OPERATION 列显示对该行执行了什么操作 (Insert/Update/Delete)。所做的这些工作不需要历史表或额外的列。
flashback version query记载的是行的改变,如果一个操作有多行的改变,如delete from tablename,那么,在flashback version query对应的也是多行。

在上述查询中,列 versions_starttime、versions_endtime、versions_xid、versions_operation 是伪列,与 ROWNUM、LEVEL 等其他熟悉的伪列相类似。其他伪列 - 如 VERSIONS_STARTSCN 和 VERSIONS_ENDSCN - 显示了该时刻的系统更改号。列 versions_xid 显示了更改该行的事务标识符。有关该事务的更多详细信息可在视图 FLASHBACK_TRANSACTION_QUERY 中找到(这个将在flashback transaction query中描述)。

当然,除了分析以上所有的变更之外,我们可以指定时间段,如
select a,b
from test versions between timestamp
to_date('2004-04-07 04:34:04','yyyy-mm-dd hh24:mi:ss')
and to_date('2004-04-07 04:34:50','yyyy-mm-dd hh24:mi:ss')

还可以使用 SCN 来找出过去的版本值。可以从伪列 VERSIONS_STARTSCN 和 VERSIONS_ENDSCN 中获得 SCN 号。以下是一个示例:
select versions_starttime, versions_endtime
from test versions
between scn 1000 and 1001




五 flashback transaction query

flashback transaction query其实是flashback version query查询的一个扩充,flashback version query我们说明了我们可以审计一段时间内表的所有改变,但是也仅仅是能发现问题,对于错误的事务,没有好的处理办法。但是flashback transaction query提供了我们办法,我们可以从FLASHBACK_TRANSACTION_QUERY中获得事务的历史以及Undo_sql,也就是说,我们审 计一个事务到底做了什么甚至可以回滚一个已经提交的事务。

flashback transaction query需要用到FLASHBACK_TRANSACTION_QUERY视图,我们先看一下视图
SQL> desc FLASHBACK_TRANSACTION_QUERY;
Name             Type           Nullable Default Comments               
---------------- -------------- -------- ------- --------------------------
XID              RAW(8)         Y        Transaction identifier   
START_SCN        NUMBER         Y        Transaction start SCN   
START_TIMESTAMP  DATE           Y        Transaction start timestamp   
COMMIT_SCN       NUMBER         Y        Transaction commit SCN  
COMMIT_TIMESTAMP DATE           Y        Transaction commit timestamp  
LOGON_USER       VARCHAR2(30)   Y        Logon user for transaction   
UNDO_CHANGE#     NUMBER         Y        1-based undo change number  
OPERATION        VARCHAR2(32)   Y        forward operation for this undo  
TABLE_NAME       VARCHAR2(256)  Y        table name to which this undo applies     
TABLE_OWNER      VARCHAR2(32)   Y        owner of table to which this undo applies
ROW_ID           VARCHAR2(19)   Y        rowid to which this undo applies         
UNDO_SQL         VARCHAR2(4000) Y        SQL corresponding to this undo  
其定义为:
select xid, start_scn, start_timestamp,
          decode(commit_scn, 0, commit_scn, 281474976710655, NULL, commit_scn)
          commit_scn, commit_timestamp,
          logon_user, undo_change#, operation, table_name, table_owner,
          row_id, undo_sql
from sys.x$ktuqqry

好,现在,我们试着回滚一个已经提交的事务。
其实,需要从FLASHBACK_TRANSACTION_QUERY获得数据,关键问题是获得事务XID,
SQL> create table test as select * from all_objects;
Table created.

SQL> set time on
11:15:48 SQL> delete from test where rownum <=10;
10 rows deleted.

11:16:10 SQL> select xid from v$transaction;
XID
----------------
04001200AE010000

11:20:09 SQL> commit;
Commit complete.

当然,我们在测试中,可以在事务没有提交的时候,获得事务的04001200AE010000。
实际情况下,我们不可能去跟踪每个事务,想要获得已提交事务的XID,就必须通过flashback version query了,如
11:30:32 SQL> select versions_xid, versions_operation
11:30:41   2    from test versions between timestamp
11:30:41   3    to_date('2004-04-08 11:15:48','yyyy-mm-dd hh24:mi:ss')
11:30:41   4    and MAXVALUE
11:30:41   5    WHERE versions_xid is not null
11:30:41   6    order by VERSIONS_STARTTIME;

VERSIONS_XID     V
---------------- -
04001200AE010000 D
04001200AE010000 D
04001200AE010000 D
04001200AE010000 D
04001200AE010000 D
04001200AE010000 D
04001200AE010000 D
04001200AE010000 D
04001200AE010000 D
04001200AE010000 D
10 rows selected.

可以看到,我们共删除了10行,对应的是10个操作。这10个操作都是同一个事务,我们现在利用这个XID来获得UNDO_SQL。

SQL>SELECT UNDO_SQL FROM FLASHBACK_TRANSACTION_QUERY
WHERE XID = '04001200AE010000';

UNDO_SQL
------------------------------------------------------------------------------
insert into "TEST"."TEST"("OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DA
insert into "TEST"."TEST"("OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DA
insert into "TEST"."TEST"("OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DA
insert into "TEST"."TEST"("OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DA
insert into "TEST"."TEST"("OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DA
insert into "TEST"."TEST"("OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DA
insert into "TEST"."TEST"("OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DA
insert into "TEST"."TEST"("OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DA
insert into "TEST"."TEST"("OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DA
insert into "TEST"."TEST"("OWNER","OBJECT_NAME","SUBOBJECT_NAME","OBJECT_ID","DA

这个删除语句对应的是10个insert语句,如果我们想回滚这个事务,我们执行这10个insert语句即可(以上语句都是完整的语句,这里因为显示问题,我就不完全显示了)。

可以看到,flashback transaction query主要用于审计一个事务,并可以回滚一个已经提交的事务。如果确定出错的事务是最后一个事务,我们利用falshback table或者flashback query就可以解决问题,但是,如果我们执行了一个错误的事务之后,又执行了一系列正确的事务,那么。利用flashback transaction query,我们甚至可以是回滚这个错误的事务。





阅读(1460) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~