Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1434011
  • 博文数量: 556
  • 博客积分: 12626
  • 博客等级: 上将
  • 技术积分: 5799
  • 用 户 组: 普通用户
  • 注册时间: 2006-01-11 15:56
个人简介

从事IT基础架构多年,发现自己原来更合适去当老师……喜欢关注新鲜事物,不仅限于IT领域。

文章分类

全部博文(556)

文章存档

2019年(6)

2018年(15)

2017年(17)

2016年(11)

2015年(2)

2014年(2)

2013年(36)

2012年(54)

2011年(100)

2010年(41)

2009年(72)

2008年(14)

2007年(82)

2006年(104)

分类: Oracle

2007-09-06 11:59:40

    oracle10g对flashback功能增加了很多,当然这些功能的机制跟以前不同(在不启用新功能的情况下,以前的机制还是可用的),这里对机制不作详细介绍了,只做记录一下使用方法:
    开启flashback的方法很简单,mount模式(有说MOUNT EXCLUSIVE模式,但似乎mount没发现什么不妥)执行ALTER DATABASE FLASHBACK ON;命令,在open数据库即可,用命令
SELECT flashback_on FROM v$database;确认,V$FLASHBACK_DATABASE_LOG和V$FLASHBACK_DATABASE_STAT视图可能检查flashback情况。DB_FLASHBACK_RETENTION_TARGET参数用来定义保存时间(单位分钟),当然这个时间不是绝对的,还有其它因素决定。
 
一、FLASHBACK DATABASE
   在不需要restore数据文件的情况下按时间点恢复数据库:
   有数据库当前存在两张表,都有数据:
SQL> select * from test.test;
      COL1 COL2       COL3
---------- ---------- ----------
         2 c          c
         2 c          c
         2 c          c
         2 c          c
         2 c          c
         2 c          c
         2 c          c
         2 c          c
         2 c          c
         2 c          c
         2 c          c
11 rows selected.
SQL> select * from test.test2;
      COL1
----------
         1
         1
         1
 
看一下当前时间:
SQL> select sysdate from dual;
SYSDATE
-----------------
20070906 10:15:14
 
然后删除一张表的记录,同时drop另外一张:
SQL> delete from test.test;
11 rows deleted.
 
SQL> commit;
Commit complete.
 
SQL> drop table test.test2;
Table dropped.
 
SQL> select * from test.test;
no rows selected
 
SQL> select * from test.test2;
select * from test.test2
                   *
ERROR at line 1:
ORA-00942: table or view does not exist
之后重启数据库到mount模式进行flashback:
SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.

SQL> startup mount
ORACLE instance started.
Total System Global Area  226492416 bytes
Fixed Size                  1261032 bytes
Variable Size             209715736 bytes
Database Buffers           12582912 bytes
Redo Buffers                2932736 bytes
Database mounted.

SQL> FLASHBACK DATABASE
TO TIMESTAMP TO_DATE
('20070906 10:15:14','YYYYMMDD HH24:MI:SS');  2    3 
Flashback complete.
 
最后可以用open resetlogs或open read only打开数据库:
SQL> alter database open resetlogs;
Database altered.
 
SQL> select * from test.test;
      COL1 COL2       COL3
---------- ---------- ----------
         2 c          c
         2 c          c
         2 c          c
         2 c          c
         2 c          c
         2 c          c
         2 c          c
         2 c          c
         2 c          c
         2 c          c
         2 c          c
11 rows selected.
 
SQL> select * from test.test2;
      COL1
----------
         1
         1
         1
两张表都已经恢复了。
不过这里要提一个我遇到的问题,在用open read only打开数据库后,再重新改为正常open数据库时会出现错误:ORA-38760: This database instance failed to turn on flashback database
这时只有关闭flashback启动才可以正常open(如果要继续用flashback就重新打开),不知道为啥会这样,猜测为open read only会对flashback log的动作有关系。
 
oracle10g允许使用ALTER TABLESPACE FLASHBACK OFF|ON命令对表空间的flashback功能进行单独控制,v$tablespace视图flashback_on字段可以看到具体内容,但要注意的是,一旦某个表空间的flashback功能被关闭了,在做flashback database的时候会报错,这时只能先offline相应的datafile,才能flashback,这个表空间只能通过传统recover的办法来恢复了,如果不恢复对应的数据文件,数据库将无法启动,除非offline drop数据文件了。另外我发现如果表空间数据没有做过任何修改是不用做恢复的,数据库启来后直接online就可以了。
另外flashback不是并不是万能的,在重建控制文件,删除表空间,shrink数据文件后,flashback都会失效。(其实其根源就是控制文件变化了),还有就是使用flashback database要在归档模式下才能用。
 
二、Flashback Drop
    这个功能可以将误删除的表恢复,初始化参数recyclebin=on(这里你会发现flashback drop功能可以不依赖database或者tablespace的flashback属性)。
首先drop一张存在的表:
SQL> select * from test.test2;
      COL1
----------
         1
         1
         1
 
SQL> drop table test.test2;
Table dropped.
 
SQL> select * from test.test2;
select * from test.test2
                   *
ERROR at line 1:
ORA-00942: table or view does not exist
 
查看系统视图dba_recyclebin可以看到drop的表已经现在对应的名字(系统自动定义的),用show recyclebin命令也可以,不过只能看用户自己属主下的表。
SQL> SELECT owner, original_name, object_name,
  2  type, ts_name, droptime, related, space
  3  FROM dba_recyclebin
  4  WHERE can_undrop = 'YES';
OWNER                          ORIGINAL_NAME
------------------------------ --------------------------------
OBJECT_NAME                    TYPE
------------------------------ -------------------------
TS_NAME                        DROPTIME               RELATED      SPACE
------------------------------ ------------------- ---------- ----------
TEST                           TEST2
BIN$OXQ8d7+dSBDgQKjACqlxVQ==$0 TABLE
USERS                          2007-09-06:16:37:32      54079          8
 
用flashback drop功能恢复表
SQL> flashback table test.test2 to before drop;
Flashback complete.
 
SQL> select * from test.test2;
      COL1
----------
         1
         1
         1
    表被非常容易恢复了。这个功能可以通过ALTER SESSION|SYSTEM SET recyclebin = OFF|ON;命令在会话级和系统级来打开关闭。
    当在recyclebin中存在多个ORIGINAL_NAME时(是允许的),每次恢复的是最近一次被drop的表(即LIFO),如果想恢复再以前被drop的版本,需要把table_name指定为要恢复的你的那个版本的系统生产的对象名就可以了,如果想所有版本都恢复出来只能改名,语法为:
FLASHBACK TABLE
TO BEFORE DROP [RENAME TO ];
这里new_name不用写属主。这里还要注意一点,recyclebin里面可以是连同表关联对象(如索引)一起保存的,但恢复的时候这些关联对象并不恢复为以前的名字,而是与系统自定义的名字一样,要向恢复以前的名字,只能自己改,这可能是因为考虑重名问题吧。
    在recyclebin里的这些对象可以被查询,但不能使用dml和ddl。
 
    recyclebin里的对象并不是永远可用的,PURGE命令可以手工清楚recyclebin的对象,这些对应也会由于自由空间紧张而自动删除的,原则上说表空间的自由空间分配是先找没有recyclebin对象的空闲空间,然后再使用被recyclebin对象占用的空间(先删最老的FIFO),最后才会自动扩展(如果设置允许的话)。我没有做测试,总之使用时注意就好。
 
    PURGE的语法比较简单,典型的命令如:
PURGE {TABLE |INDEX }
PURGE TABLESPACE [USER ] (可能会清其它表空间的关联对象)
再有多个同原始名的记录存在时,也是先删最老的(FIFO)
 
    flashback drop有几点要注意的地方:
recycle bin只能在非system表空间和本地管理表空间上使用(关联对象在字典管理表空间也能有效保护),FGA和VPD定义下的表不能放到recyclebin里,Bitmap join indexes,Materialized view logs,Referential integrity constraints是不被保护的,还有就是删除一张表之前所删除的索引也不能被保护。
 
三、Flashback Versions Query
    oracle10g新增的这个功能还是挺有意思的,它可以把一张表曾经修改过的各个版本变化查询出来。这个功能的语法看起来有点复杂:
SELECT [Pseudocolumns]…
FROM …
VERSIONS BETWEEN
{SCN|TIMESTAMP {expr|MINVALUE} AND
{expr|MAXVALUE}}
[AS OF {SCN|TIMESTAMP expr}]
WHERE [Pseudocolumns…]…
这里Pseudocolumn主要包括:
VERSIONS_STARTSCN: 行数据版本被创建时的SCN
VERSIONS_STARTTIME: 行数据版本被创建时的Time stamp
VERSIONS_ENDSCN: 行数据版本结束时的SCN
VERSIONS_ENDTIME: 行数据版本结束时的Time stamp
VERSIONS_XID: 行版本创建时的Transaction identifier
VERSIONS_OPERATION: 这个事务执行的操作
VERSIONS_STARTSCN和VERSIONS_STARTTIME在查询版本范围之外或者UNDO_RETENTION时间之前的时候,可能会为空;VERSIONS_ENDSCN和VERSIONS_ENDTIME在当前版本或者一个delete版本里会为空。
 
据个例子就好理解了:
 
创建一个表并插入记录
SQL> create table test.test3 (col number);
Table created.
 
SQL> insert into test.test3 values(1);
1 row created.
 
SQL> commit;
Commit complete.
 
使用Flashback Versions Query:
SQL> SELECT versions_xid AS XID,
  2  versions_startscn AS START_SCN,
  3  versions_endscn AS END_SCN,
  4  versions_operation AS OPERATION,
  5  col
  6  FROM test.test3
  7  VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE;
XID               START_SCN    END_SCN O        COL
---------------- ---------- ---------- - ----------
01002A00BC010000    1007043            I          1
 
这里得到了一个初始的scn,以及col字段新插入了内容为1的一条记录,下面我修改这个记录:
SQL> update test.test3 set col=2;
1 row updated.
 
SQL> commit;
Commit complete.
 
SQL> SELECT versions_xid AS XID,          
  2  versions_startscn AS START_SCN,
  3  versions_endscn AS END_SCN,
  4  versions_operation AS OPERATION,
  5  col
  6  FROM test.test3
  7  VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE;
XID               START_SCN    END_SCN O        COL
---------------- ---------- ---------- - ----------
06000E00EF010000    1007247            U          2
01002A00BC010000    1007043    1007247 I          1
这时查询多了一个版本,可以看到这个新版本的START_SCN跟上一个版本的END_SCN是一样的,这个版本中col字段被update为2了,然后我们删除这个记录:
SQL> delete from test.test3;
1 row deleted.
 
SQL> commit;
Commit complete.
 
SQL> SELECT versions_xid AS XID,
  2  versions_startscn AS START_SCN,
  3  versions_endscn AS END_SCN,
  4  versions_operation AS OPERATION,
  5  col
  6  FROM test.test3
  7  VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE;
XID               START_SCN    END_SCN O        COL
---------------- ---------- ---------- - ----------
06002A00EF010000    1007310            D          2
06000E00EF010000    1007247    1007310 U          2
01002A00BC010000    1007043    1007247 I          1
col为2的那条记录被delete了。
下面看下VERSIONS和AS OF一起用的效果:
SQL> SELECT versions_xid AS XID,
versions_startscn AS START_SCN,
  2    3  versions_endscn AS END_SCN,
  4  versions_operation AS OPERATION, col
  5  FROM test.test3
  6  VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE
  7  AS OF SCN 1007247;
XID               START_SCN    END_SCN O        COL
---------------- ---------- ---------- - ----------
06000E00EF010000    1007247            U          2
01002A00BC010000    1007043    1007247 I          1
这时只能看到scn 1007247以前的版本,这对于事务处理较多的表还是挺有用的。
 
同样,Flashback Versions Query也有很多局限。External tables,Temporary tables和Fixed tables是不被支持的,视图不能用versions子句来查询,不过在定义view的时候使用它。另外它不能跨越一个DDL操作,换句话说truncate后的表也就看不到以前的版本了:
SQL> truncate table test.test3;
Table truncated.
 
SQL> SELECT versions_xid AS XID,
  2  versions_startscn AS START_SCN,
  3  versions_endscn AS END_SCN,
  4  versions_operation AS OPERATION,
  5  col
  6  FROM test.test3
  7  VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE;
no rows selected
不知道11g有没有增强,以后再看了。
 
四、Flashback Transaction Query
    从名字就能看处理,这个功能可以将事务处理的过程恢复处理,只需要查一下FLASHBACK_TRANSACTION_QUERY 这个视图就可以了:
 
SQL> select * from FLASHBACK_TRANSACTION_QUERY where table_name='TEST3';
XID               START_SCN START_TIM COMMIT_SCN COMMIT_TI
---------------- ---------- --------- ---------- ---------
LOGON_USER                     UNDO_CHANGE# OPERATION
------------------------------ ------------ --------------------------------
TABLE_NAME
--------------------------------------------------------------------------------
TABLE_OWNER                      ROW_ID
-------------------------------- -------------------
UNDO_SQL
--------------------------------------------------------------------------------
01002A00BC010000    1006988 07-SEP-07    1007043 07-SEP-07
SYS                                       1 INSERT
TEST3
TEST                             AAANOqAAEAAAAGsAAA
delete from "TEST"."TEST3" where ROWID = 'AAANOqAAEAAAAGsAAA';
06002A00EF010000    1007247 07-SEP-07    1007310 07-SEP-07
SYS                                       1 DELETE
TEST3
TEST                             AAANOqAAEAAAAGsAAA
insert into "TEST"."TEST3"("COL") values ('2');
06000E00EF010000    1007043 07-SEP-07    1007247 07-SEP-07
SYS                                       1 UPDATE
TEST3
TEST                             AAANOqAAEAAAAGsAAA
update "TEST"."TEST3" set "COL" = '1' where ROWID = 'AAANOqAAEAAAAGsAAA';
(COMMIT_TIMESTAMP和COMMIT_SCN为空时,表示事务正在活动中。)
 
回顾一下前面对test.test3表操作的情况,对比一下就能发现,XID是一一对应的,而且undo_sql列都是当时的反相操作语句。
有了这个表,我们可以按事务id查一个事务所做的操作:
select * from FLASHBACK_TRANSACTION_QUERY
where xid=HEXTORAW('06002A00EF010000')
ORDER BY undo_change#;
还可以按时间段来查:
SELECT × FROM flashback_transaction_query
WHERE start_timestamp >= TO_TIMESTAMP
('2007-09-07 11:00:00','YYYY-MM-DD HH:MI:SS')
AND commit_timestamp <= TO_TIMESTAMP
('2007-09-07 11:30:00','YYYY-MM-DD HH:MI:SS');
(所以半小时内开始并提交过的事务)
 
使用Flashback Transaction Query仍然无法完全展现DDL,因为都是数据字典的操作,如果对数据字典比较熟,有些动作还是可以查出来的。
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;命令可以增加更充足的信息用于事务查询,不过我相信redo量也会增加不少吧。另外,执行对象需要SELECT ANY TRANSACTION权限。
 
五、Flashback Table
   这个功能使用方法跟flashback drop比较相似(当然机制完全不同了),在操作之前需要先执行ALTER TABLE table_name ENABLE ROW MOVEMENT;
这是因为flashback功能使用dml操作,通过修改数据块来恢复记录的,它本身并不保护记录的那些rowid,因此ENABLE ROW MOVEMENT是进行flashback前必须要做的。
 
ENABLE ROW MOVEMENT之后可以执行:
FLASHBACK TABLE employees
TO TIMESTAMP (SYSDATE-1);
恢复表到一个时间点,也可以执行:
FLASHBACK TABLE table1, table2
TO SCN 5525293 ENABLE TRIGGERS;
将一组一致性相关的表恢复到一个scn点上,这里enable triggers参数可以保持表上定义的trigger在执行flashback table时不被disable(确实是要disable的)
 
flashback table很强的一点在于,它可以将表多次恢复到以前的不同的时间点上,据个例子:
在11点时候,将表flashback到10点的状态,而之后发现这不是想要的版本,然后你在11点10分的时候可以执行另外一个flashback,将其恢复到10点半时你所需要的那个版本上。
SQL> select * from test.test3;
       COL
----------
         1
         2
 
SQL> select sysdate from dual;
SYSDATE
-----------------
20070907 16:52:41
 
SQL> insert into test.test3 values(3);
1 row created.
 
SQL> commit;
Commit complete.
 
SQL> select * from test.test3;
       COL
----------
         1
         2
         3
 
SQL> flashback table test.test3 to timestamp (to_date('20070907 16:52:41','yyyymmdd hh24:mi:ss'));
Flashback complete.
 
SQL> select * from test.test3;
       COL
----------
         1
         2
以上的例子可以看到,表数据已经恢复了。
flashback table不能操作系统表,flashback table动作受到事务完整性的约束,发现相关对象不一致的时候,falshback table就会中断,统计信息也是不能flashback的,flashback table会自动维护索引,但删除的索引是无法重建的。另外跟以前一样,flashback不能跨越ddl操作,truncate table依然不能恢复:
SQL> truncate table test.test3;
Table truncated.
 
SQL> flashback table test.test3 to timestamp (to_date('20070907 16:52:41','yyyymmdd hh24:mi:ss'));
flashback table test.test3 to timestamp (to_date('20070907 16:52:41','yyyymmdd hh24:mi:ss'))
                     *
ERROR at line 1:
ORA-01466: unable to read data - table definition has changed
 
所以truncate table一定要谨慎,确认好在做。
 
六、Restore Points
    定义Restore Points分为两种方式:Normal restore points和Guaranteed restore points。
普通的Restore Points其实就是scn或者time stamp的同义词,便于管理员在flashback database或table时的使用,而Guaranteed restore points就复杂一些了,它用到了flashback logs。因此前者在恢复的时候不一定会成功,而后者则是要保证恢复的成功,因此在使用的时候也要注意flash recovery area空间的使用,当空间满的时候数据库会暂时中止,类似于归档空间满,同时该模式要运行在归档模式下,这里rman会保证归档日志不被设置为obsolete,直到Guaranteed restore points被删除。
    Restore points是记录在控制文件中的,周期随着CONTROL_FILE_RECORD_KEEP_TIME参数而老化退出,当然guaranteed restore point不会老化退出。使用guaranteed restore point时,Flashback Database可以打开也可以不打开,不打开的时候设置和删除guaranteed restore point都要在mount状态下来做,而且恢复是只能恢复到设置的点上,其实作为生产变化前的备份,这种方式还是很不错的。
    下面看看怎么将restore point:
SQL> create restore point rptest;
Restore point created.
 
SQL> select * from v$restore_point;
       SCN DATABASE_INCARNATION# GUA STORAGE_SIZE
---------- --------------------- --- ------------
TIME
---------------------------------------------------------------------------
NAME
--------------------------------------------------------------------------------
   1015633                     8 NO             0
10-SEP-07 10.21.42.000000000 AM
RPTEST
这里创建了一个普通的restore point,作个测试:
有张空表,插入一条记录:
SQL> select * from test.test3;
no rows selected
 
SQL> insert into test.test3 values(1);
1 row created.
 
SQL> commit;
Commit complete.
 
SQL> select * from test.test3;
       COL
----------
         1
 
用刚才建的restore point来恢复:
SQL> flashback table test.test3 to restore point rptest;
Flashback complete.
 
SQL> select * from test.test3;
no rows selected
刚才的记录没了。
 
在建个guarantee restore point试试:
SQL> create restore point rptest2 guarantee flashback database;
create restore point rptest2 guarantee flashback database
*
ERROR at line 1:
ORA-38784: Cannot create restore point 'RPTEST2'.
ORA-38787: Creating the first guaranteed restore point requires mount mode when
flashback database is off.
在数据库open时建立报错了,再试试mount时:
SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.

SQL> startup mount
ORACLE instance started.
Total System Global Area  226492416 bytes
Fixed Size                  1261032 bytes
Variable Size             201327128 bytes
Database Buffers           20971520 bytes
Redo Buffers                2932736 bytes
Database mounted.

SQL> create restore point rptest2 guarantee flashback database;
Restore point created.
 
SQL> alter database open;
Database altered.
 
SQL> select * from v$restore_point where name='RPTEST2';
       SCN DATABASE_INCARNATION# GUA STORAGE_SIZE
---------- --------------------- --- ------------
TIME
---------------------------------------------------------------------------
NAME
--------------------------------------------------------------------------------
   1016602                     8 YES      8192000
10-SEP-07 10.37.49.000000000 AM
RPTEST2
可以看到STORAGE_SIZE有数值了,同时在服务器上看到flash_recovery_area空间开始生成flashback log了。
 
以上就是oracle10g新提供的一下flashback功能,感觉上oracle有意继续将flashback发扬光大,新出的11g上应该可以看到更多更完善的有趣功能吧。
 
最后再记录几个额外的内容:
首先可以用ALTER TABLESPACE undotbs1 RETENTION GUARANTEE;命令将undo空间设置为GUARANTEE状态,因为从上面的介绍可以看到,flashback功能大部分还是基于undo retention来实现的,使用RETENTION GUARANTEE可以更好的保护unexpired undo data,使flashback功能实现的跟从容。
另外SCN_TO_TIMESTAMP和TIMESTAMP_TO_SCN两个函数可以实现scn和time stamp的转(3秒映射一次,以前为5秒),例如:
SQL> SELECT current_scn, SCN_TO_TIMESTAMP(current_scn)
  2  FROM v$database;
CURRENT_SCN
-----------
SCN_TO_TIMESTAMP(CURRENT_SCN)
---------------------------------------------------------------------------
    1018648
10-SEP-07 11.10.32.000000000 AM
 
最后说一下权限,flashback database需要sysdba,flashback table和Flashback Versions Query需要FLASHBACK ANY TABLE(可以是对象权限),Flashback Transaction Query之前提过,需要SELECT ANY TRANSACTION。
 
写完收工。
 
阅读(822) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~