Oracle Flashback

                                                                                                         作者:吴伟龙

 

Flashback 技术是以Undo segment中的内容为基础的,因此受限于UNDO_RETENTON参数。要使用flashback的特性,必须启用自动撤销管理表空间。

 

在Oracle 10g中, Flash back包括如下组件:FlashbackDatabase,Flashback Drop,Flashback Table和Flashback Query(分Flashback Query, FlashbackVersion Query, Flashback Transaction Query 三种)

 

一. FlashbackDatabase

 

Flashback Database 功能非常类似与RMAN的不完全恢复,它可以依赖于Flashback log日志将整个数据库回退到过去的某个时点的状态。比RMAN更快速和高效。因此Flashback Database可以看作是不完全恢复的替代技术。但它也有一些限制。

 

如下:

1. Flashback Database不能解决Media Failure,这种错误RMAN恢复仍是唯一首选

2. 如果删除了数据文件或者利用Shrink技术缩小数据文件大小,这时不能用Flashback Database技术回退到改变之前的状态,这时候就必须先利用RMAN把删除之前或者缩小之前的文件备份restore出来,然后利用Flashback Database 执行剩下的Flashback Datbase。

3. 如果控制文件是从备份中恢复出来的,或者是重建的控制文件,也不能使用Flashback Database。

4. 使用Flashback Database锁能恢复到的最早的SCN,取决与Flashback Log中记录的最早SCN。

 

Flashback Database由如下四部分组成:

1、  Recover Writer(RVWR)后台进程,

2、  Flashback Database Log日志

3、  Flash Recovery Area 山会区

 

一旦数据库启用了FlashbackDatabase,则RVWR进程会启动,该进程会向Flash Recovery Area中写入Flashback Database Log,这些日志包括的是数据块的 " 前镜像(before image)",这也是Flashback Database 技术不完全恢复块的原因。

 

查看Flashback需要用到的进程是否启用:

[oracle@dba ~]$ ps -ef|grep rvw

 

oracle  12620 12589 0 13:21 pts/1    00:00:00 grep rvw

 

 

 

 

 

启用FlashbackDatabase

 

数据库的FlashbackDatabase功能缺省是关闭的,要想启用这个功能,需要做如下配置:

 

1.      配置Flash Recovery Area

 

   要想使用Flashback Database,必须使用Flash Recovery Area,因为Flashback Database Log只能保存在这里。要配置的2个参数(一个是大小,一个是位置)。如果数据库是RAC,flashrecovery area 必须位于共享存储中。数据库必须处于archivelog模式.

 

启用Flash Recovery Area

 

SQL> alter system setDB_RECOVERY_FILE_DEST_SIZE=2G scope=both;

System altered.

 

SQL> alter system setDB_RECOVERY_FILE_DEST=' C:\oracle\product\10.2.0\flash_back';

System altered.

 

禁用Flash Recovery Area

 

SQL> alter system setDB_RECOVERY_FILE_DEST='' ;

System altered.

 

对于Flash Recovery Area,Oracle是这样建议的,flashrecovery area设置的越大,flashback database的恢复能力就越强,因此建议flash recovery area能够放的下所有的数据文件,增量备份,以及所有尚未备份的归档文件,当然还有它自己产生的flashback logs。

 

在数据库运行过程中,oracle自动向该区域写入文件,当剩余空间不足15%的时候,它就会在alert中增加警告,提示你空间不足。但此时不会影响数据库的正常运转,直到所有空间统统被用掉之后,oracle首先尝试删除寻些过期的文件,冗余文件或备份过的文件,如果这些做完了,还是没有空闲空间的话,数据库就被hang住了。

 

 

对于因FlashRecovery Area导致的数据库hang的处理,请参考:

 


或者

http://space.itpub.net/?uid-20674423-action-viewspace-itemid-715734

 

 

2. 启用数据库Flashback功能

 

 

1). 数据库启动到mount状态

 

SQL> startup mount;

 

2). 检查Flashback功能,缺省时功能是关闭的。

 

SQL> selectname,current_scn,open_mode,flashback_on from v$database;

 

NAME       CURRENT_SCN  OPEN_MODE   FLASHBACK_ON

------------------  --------------------   ---------------       ---------------

WWL           1069647       READ WRITE           NO

 

SQL>

 

 

3). 启动Flashback功能,(首先要开启归档,后才可应用Flashback)

 

SQL> alter database flashback on;

alter database flashback on

*

ERROR at line 1:

ORA-38706: Cannot turn on FLASHBACKDATABASE logging.

ORA-38707: Media recovery is not enabled.

 

 

SQL> show parameterdb_flashback_retention

 

NAME                     TYPE              VALUE

-------------------            ----------------------     ------------------------------

db_flashback_retention_target       integer           1440

SQL> archive log list;

Database log mode             No Archive Mode

Automatic archival             Disabled

Archive destination            C:\oracle\product\10.2.0\db_1\RDBMS

Oldest online log sequence     16

Current log sequence           18

SQL> alter database archivelog;

 

Database altered.

 

SQL> archive log list;

Database log mode             Archive Mode

Automatic archival             Enabled

Archive destination            C:\oracle\product\10.2.0\db_1\RDBMS

Oldest online log sequence     16

Next log sequence to archive   18

Current log sequence           18

SQL> alter database flashback on;

 

数据库已更改。

 

 

SQL> selectname,current_scn,open_mode,flashback_on from v$database;

 

NAME       CURRENT_SCN  OPEN_MODE   FLASHBACK_ON

------------------  --------------------   ---------------       ---------------

WWL           1069647       READ WRITE           YES

 

SQL>

 

 

4). 设置初始化参数:DB_FLASHBACK_RETENTION_TARGET:

 

 

SQL>alter system setdb_flashback_retention_target=1440 scope=both;

 

该参数用来控制flashback_log数据保留的时间,或者说,你希望flashback database能够恢复的最早的时间点。默认值是1440,单位是minute,即24小时,需要注意的是该参数虽然未直接指定flash recovery area大小,但却受其制约,举个例子假如数据库每天有10%左右的数据变动的话,如果该初始化参数值设置为1440,则flashrecovery area 的大小至少要是当前数据库实际容量的10%,如果该初始化参数设置为2880,则flash recovery area的大小就至少是数据库所占容量的20%。

 

 

5). 启动数据库

 

SQL>alter database open;

 

 

 

 

 

Flashback Database操作示例

 

 

做操作前先备份数据库

 

RMAN> backup database;

 

 

1. 检查是否启动了flash recovery area:­

 

SQL> show parameter db_recovery_file

 

NAME                   TYPE        VALUE

 

------------------------------------  ----------- ------------------------------

 

db_recovery_file_dest       tring       D:\oracle/flash_recovery_area

 

db_recovery_file_dest_size  big integer 1G

 

 

2. 检查是否启用了归档­

 

SQL> archive log list;

 

数据库日志模式     存档模式

 

自动存档           启用

 

存档终点            USE_DB_RECOVERY_FILE_DEST

 

最早的联机日志序列  9

 

下一个存档日志序列  11

 

当前日志序列        11

 

 

3. 检查是否启用了flashback database

 

SQL> select flashback_on fromv$database;

 

FLASHBACK_ON    

 

 ------------------

 

YES              

 

 

4. 查询当前的scn­

 

SQL> SELECT CURRENT_SCN FROM V$DATABASE;

 

 

CURRENT_SCN

 

-----------

 

947921

 

 

5. 查询当前的时间及表内容

 

SQL> select to_char(sysdate,'yyyy-mm-ddhh24:mi:ss')time from dual;

 

TIME

--------------------------------------

2012-04-01 15:35:18

 

SQL> select count(*) from wwl;

 

 COUNT(*)

----------

       10

 

SQL> select * from wwl;

 

       ID NAME

---------- --------------------

        1 wwl

        2 wwl

        3 wwl

        4 wwl

        5 wwl

        6 xgx

        7 xgx

        8 xgx

        9 xgx

       10 xgx

 

10 rows selected.

 

6、删除表 wwl

SQL> drop table wwl;

 

Table dropped.

 

SQL> commit;

 

Commit complete.

 

SQL>

SQL> select to_char(sysdate,'yyyy-mm-ddhh24:mi:ss')time from dual;

 

TIME

--------------------------------------

2012-04-01 15:37:01

 

SQL>

7. Flashback Database实际是对数据库的一个不完全恢复操作,因为需要关闭数据库重启到mount状态。

SQL> shutdown immediate

Database closed.

Database dismounted.

ORACLE instance shut down.

SQL> startup mount;

ORACLE instance started.

 

Total System Global Area 1610612736 bytes

Fixed Size                  2066080 bytes

Variable Size             385878368 bytes

Database Buffers         1207959552 bytes

Redo Buffers               14708736 bytes

Database mounted.

SQL>

 

 

8. 执行恢复:Flashback恢复分为两种;

1、基于时间点的恢复

 

SQL> flashback database to timestampto_timestamp('2012-04-01 15:37:01','yyyy-mm-dd hh24:mi:ss');

 

Flashback complete.

 

 

2、基于SCN号的恢复

SQL> Flashback database to scn 947921;

Flashback complete

 

 

9. 打开数据库:

 

在执行完flashbackdatabase命令之后,oracle 提供了两种方式让你修复数据库:

 

1). 直接alter database open resetlogs打开数据库,当然,指定scn 或者timestamp时间点之后产生的数据统统丢失。

 

2). 先执行alter database open read only命令以read-only 模式打开数据库,然后立刻通过逻辑导出的方式将误操作涉及表的数据导出,再执行recover database命令以重新应用数据库产生的redo,将数据库修复到flashbackdatabase操作前的状态,然后再通过逻辑导入的方式,将之前误操作的表重新导入,这样的话对现有数据的影响最小,不会有数据丢失。

 

 

这里演示,就以resetlogs方式打开:

 

SQL> alter database open resetlogs;

 

数据库已更改。

 

 

验证数据(可以看到数据已经全部恢复了):

 

SQL> select count(*) from wwl;

 

 COUNT(*)

----------

       10

 

SQL> select * from wwl;

 

       ID NAME

---------- --------------------

        1 wwl

        2 wwl

        3 wwl

        4 wwl

        5 wwl

        6 xgx

        7 xgx

        8 xgx

        9 xgx

       10 xgx

 

10 rows selected.

 

 

和FlashbackDatabase相关的2个视图:

 

1. V$database

 

 这个视图可以查看是否启用了Flashback database功能

 

SQL> select flashback_on fromv$database;

 

FLASHBACK_ON

 

------------------

 

YES

 

 

2. V$flashback_database_log

 

 Flashback Database 所能回退到的最早时间,取决与保留的Flashback DatabaseLog

 

Oldest_flashback_scn / Oldest_flashback_time:这两列用来记录可以恢复到最早的时点

 

Flashback_size: 记录了当前使用的Flash Recovery Area 空间的大小

 

Retention_target:

 

Estimated_flashback_size:根据策略对需要的空间大小的估计值

SQL> select oldest_flashback_scn, to_char(oldest_flashback_time,'yyyy-mm-ddhh24:mi:ss'), retention_target,flashback_size, estimated_flashback_size fromv$flashback_database_log;

 

OLDEST_FLASHBACK_SCN TO_CHAR(OLDEST_FLASHBACK_TIME,'YYYY-MMRETENTION_TARGET FLASHBACK_SIZE ESTIMATED_FLASHBACK_SIZE

-------------------- ------------------------------------------------------ -------------- ------------------------

             1070299 2012-04-0115:08:40                               1440       15941632                428433408

 

3. V$flashback_database_stat

 

这个视图用来对Flashbacklog空间情况进行更细粒度的记录和估计。这个视图以小时为单位记录单位时间内数据库的活动量,Flashback_Data代表Flashbacklog产生数量,DB_Date代表数据改变数量,Redo_Date代表日志数量,通过这3个数量可以反映出数据的活动特点,更准确的预计Flash RecoveryArea的空间需求

 

SQL> alter session setnls_date_format='yyyy-mm-dd hh24:mi:ss';

 

Session altered.

 

SQL> select *fromv$flashback_database_stat;

 

BEGIN_TIME          END_TIME            FLASHBACK_DATA    DB_DATA REDO_DATA ESTIMATED_FLASHBACK_SIZE

------------------- --------------------------------- ---------- ---------- ------------------------

2012-04-01 15:40:47 2012-04-0116:00:42        5029888    9658368     92160                        0

 

SQL>

 

Flashback DROP

 

Flashback Drop 是从Oracle 10g 开始出现的,用于恢复用户误删除的对象(包括表,索引等),这个技术依赖于Tablespace Recycle Bin(表空间回收站),这个功能和windows的回收站非常类似。

 

 

Flashback 不支持sys用户. system表空间下的对象,也不能从回收站里拿到。故使用SYS或者SYSTEM用户登陆时, show recyclebin为空。

 

 

 

1. Tablespace Recycle Bin

 

 

从Oracle 10g开始,每个表空间都会有一个叫作回收站的逻辑区域,当用户执行drop命令时,被删除的表和表的关联对象(包括索引,约束,触发器,LOB段,LOB index段) 不会被物理删除,这些对象先转移到回收站中,这就给用户提供了一个恢复的可能。

 

 

 

初始化参数recyclebin用于控制是否启用recyclebin功能,缺省是ON,可以使用OFF关闭。

 

 

SQL> show parameter recycle

 

 

NAME                    TYPE        VALUE

 

----------------------------------------------- ------------------------------

 

buffer_pool_recycle            string

 

db_recycle_cache_size         big integer 0

 

recyclebin                    string      on

 

 

禁用该功能:

 

SQL> alter system set recyclebin=off;

 

SQL> alter system set recyclebin=on;

 

 

SQL> alter session set recyclebin=off;

 

SQL> alter session set recyclebin=on;

 

 

禁用后删除的对象将直接删除,不会写到Recycle中,当然在删除时,指定purge参数,表也将直接删除,不会写到recyclebin中。

SQL> drop table name purge;

 

 

查看recyclebin中的对象列表:

 

SQL> select * from wwl;

 

       ID NAME

---------- --------------------

        1 wwl

        2 wwl

        3 wwl

        4 wwl

        5 wwl

        6 xgx

        7 xgx

        8 xgx

        9 xgx

       10 xgx

 

10 rows selected.

 

SQL> drop table WWL;

 

表已删除。

 

ORIGINAL NAME    RECYCLEBIN NAME                OBJECT TYPE DROP TIME

---------------------------------------------- ------------ -------------------

WWL              BIN$44hxTH+iQ3O2R22elviUQg==$0TABLE        2012-04-01:15:36:15

 

 

查看recyclebin中对象:

SQL> selectobject_name,original_name,operation,type,createtime,droptime,dropscn fromrecyclebin;

 

OBJECT_NAME                    ORIGINAL_N OPERATION          TYPE  CREATETIME           DROPTIME        DROPSCN

------------------------------ ---------------------------- ------ -------------------- -------------------- ----------

BIN$44hxTH+iQ3O2R22elviUQg==$0 WWL        DROP               TABLE  2012-04-01:15:32:13  2012-04-01:15:36:15     1071650

查看recyblebin对象里的内容:

 

SQL> select * from"BIN$44hxTH+iQ3O2R22elviUQg==$0";

 

       ID NAME

---------- --------------------

        1 wwl

        2 wwl

        3 wwl

        4 wwl

        5 wwl

        6 xgx

        7 xgx

        8 xgx

        9 xgx

       10 xgx

 

10 rows selected.

 

SQL>

 

表空间的RecycleBin区域只是一个逻辑区域,而不是从表空间上物理的划出一块区域固定用于回收站,因此Recycle Bin是和普通对象共用表空间的存储区域,或者说是Recycle Bin的对象要和普通对象抢夺存储空间。当发生空间不够时,Oracle会按照先入先出的顺序覆盖RecycleBin中的对象。也可以手动的删除RecycleBin占用的空间。

 

1). Purge tablespace tablespace_name :用于清空表空间的Recycle Bin

 

2). Purge tablespace tablespace_name useruser_name:清空指定表空间的RecycleBin中指定用户的对象

 

3). Purge recyclebin:删除当前用户的Recycle Bin中的对象

 

4). Purge dba_recyclebin:删除所有用户的Recycle Bin中的对象,该命令要sysdba权限

 

5). Drop table table_name purge: 删除对象并且不放在Recycle Bin中,即永久的删除,不能用Flashback恢复。

 

6). Purge index recycle_bin_object_name:当想释放Recycle bin的空间,又想能恢复表时,可以通过释放该对象的index所占用的空间来缓解空间压力。因为索引是可以重建的。

 

2. Flashback Drop

 

SQL> flashback table wwl to before drop;

 

Flashback complete.

 

SQL> select * from wwl;

 

       ID NAME

---------- --------------------

        1 wwl

        2 wwl

        3 wwl

        4 wwl

        5 wwl

        6 xgx

        7 xgx

        8 xgx

        9 xgx

       10 xgx

 

10 rows selected.

 

SQL>

 

当我们删除表WWL后,在新建表WWL,这时在恢复的时候就会报错,此时我们在闪回时,对表重命名就可以了:

 

SQL> drop table wwl;

 

表已删除。

 

SQL> create table wwl

 

 2  (id number(5));

 

表已创建。

 

SQL> flashback table wwl to before drop;

 

flashback table a to before drop

 

*

 

第 1 行出现错误:

 

ORA-38312: 原始名称已被现有对象使用

 

 

SQL> flashback table wwl to before droprename to wwl01;

 

闪回完成。

 

SQL> select * from wwl01;

 

       ID NAME

---------- --------------------

        1 wwl

        2 wwl

        3 wwl

        4 wwl

        5 wwl

        6 xgx

        7 xgx

        8 xgx

        9 xgx

       10 xgx

 

10 rows selected.

 

当我们删除表wwl,在新建表wwl,在删除它,这是在Recycle Bin中就会有2个相同的表明,此时恢复我们就要指定object_name才行.

 

 

SQL> select * from ww0l;

 

       ID NAME

---------- --------------------

        1 wwl

        2 wwl

        3 wwl

        4 wwl

        5 wwl

        6 xgx

        7 xgx

        8 xgx

        9 xgx

       10 xgx

 

10 rows selected.

 

SQL> drop table wwl01;

 

表已删除。

 

SQL> create table wwl01(name varchar(10));

 

表已创建。

 

SQL> drop table wwl01;

 

表已删除。

 

SQL> select original_name,object_namefrom recyclebin;

 

ORIGINAL_NAME                    OBJECT_NAME

 

--------------------------------            ------------------------------

 

WWL01                               BIN$vYuv+g9fTi2exYP9X2048Q==$0

 

WWL01                               BIN$geQ9+NekSjuRvzG+TqDVWw==$0

 

SQL> flashback table"BIN$vYuv+g9fTi2exYP9X2048Q==$0" to before drop;

 

闪回完成。

 

SQL> select * from ww0l;

 

       ID NAME

---------- --------------------

        1 wwl

        2 wwl

        3 wwl

        4 wwl

        5 wwl

        6 xgx

        7 xgx

        8 xgx

        9 xgx

       10 xgx

 

10 rows selected.

一旦完成闪回恢复,Recycle Bin中的对象就消失了. Flashback Drop需要注意的地方:

 

1). 只能用于非系统表空间和本地管理的表空间

 

2). 对象的参考约束不会被恢复,指向该对象的外键约束需要重建。

 

3). 对象能否恢复成功,取决与对象空间是否被覆盖重用。

 

4). 当删除表时,信赖于该表的物化视图也会同时删除,但是由于物化视图并不会被放入recycle bin,因此当你执行flashback table to before drop时,也不能恢复依赖其的物化视图,需要dba 手工介入重新创建。

 

5). 对于Recycle Bin中的对象,只支持查询.

 

 

 

 

 

Flashback Query

 

Flashback 是ORACLE自9i 就开始提供的一项特性,在9i中利用oracle查询多版本一致的特点,实现从回滚段中读取表一定时间内操作过的数据,可用来进行数据比对,或者修正意外提交造成的错误数据,该项特性也被称为Flashback Query。

 

 

一、FlashbackQuery

正如前言中所提,FlashbackQuery是利用多版本读一致性的特性从UNDO表空间读取操作前的记录数据!

 

 

什么是多版本读一致性

Oracle 采用了一种非常优秀的设计,通过undo数据来确保写不堵塞读,简单的讲,不同的事务在写数据时,会将数据的前映像写入undo表空间,这样如果同时有其它事务查询该表数据,则可以通过undo 表空间中数据的前映像来构造所需的完整记录集,而不需要等待写入的事务提交或回滚。

 

 

flashback query 有多种方式构建查询记录集,记录集的选择范围可以基于时间或基于scn,甚至可以同时查询出记录在undo表空间中不同事务时的前映象。用法与标准查询非常类似,要通过flashbackquery查询undo 中的撤销数据,最简单的方式只需要在标准查询语句的表名后面跟上as oftimestamp(基于时间)或as of scn(基于scn)即可。as of timestamp|scn的语法是自9iR2

 

 

1、  As of timestamp 的示例:

 

SQL> alter session setnls_date_format='YYYY-MM-DD hh24:mi:ss';

 

Session altered.

 

SQL> select sysdate from dual;

 

SYSDATE

-------------------

2012-04-01 16:27:59

 

SQL> select count(*) from wwl;

 

 COUNT(*)

----------

       10

 

SQL> delete from wwl;

 

10 rows deleted.

 

SQL>

 

模拟用户误操作,删除数据

 

SQL> delete from wwl;

 

10 rows deleted.

 

SQL> commit;

 

Commit complete.

 

SQL>

SQL> select * from wwl;

 

no rows selected

 

SQL>

查看删除之前的状态:

假设当前距离删除数据已经有3分钟左右的话:

SQL> select * from wwl as of timestampsysdate-5/1440;

 

       ID NAME

---------- --------------------

        1 wwl

        2 wwl

        3 wwl

        4 wwl

        5 wwl

        6 xgx

        7 xgx

        8 xgx

        9 xgx

       10 xgx

 

10 rows selected.

 

SQL>

或者(注意:时间是写删除前的时间):

 

SQL> select * from wwl as of timestampto_timestamp('2012-4-1 16:25:00','YYYY-MM-DD hh24:mi:ss');

 

       ID NAME

---------- --------------------

        1 wwl

        2 wwl

        3 wwl

        4 wwl

        5 wwl

        6 xgx

        7 xgx

        8 xgx

        9 xgx

       10 xgx

 

10 rows selected.

 

SQL>

用FlashbackQuery恢复之前的数据:

 

SQL> Insert into wwl select * from wwlas of timestamp to_timestamp('2012-4-1 16:25:00','YYYY-MM-DD hh24:mi:ss');

 

10 rows created.     ---这里告诉你数据已经闪回成功,接着下面的检查

 

SQL> commit;

 

Commit complete.

 

 

SQL> select * from wwl;

 

       ID NAME

---------- --------------------

        1 wwl

        2 wwl

        3 wwl

        4 wwl

        5 wwl

        6 xgx

        7 xgx

        8 xgx

        9 xgx

       10 xgx

 

10 rows selected.

 

SQL>

如上述示例中所表示的,as of timestamp的确非常易用,但是在某些情况下,我们建议使用as of scn 的方式执行flashback query,比如需要对多个相互有主外键约束的表进行恢复时,如果使用as oftimestamp的方式,可能会由于时间点不统一的缘故造成数据选择或插入失败,通过scn方式则能够确保记录的约束一致性。

 

 

2.Flashback基于SCN的恢复示例

 

 

查看SCN:

 

SQL> SELECT CURRENT_SCN FROM V$DATABASE;

 

CURRENT_SCN

 

-----------

 

1073555

 

 

删除数据:

SQL> delete from wwl;

 

10 rows deleted.

 

SQL> commit;

 

Commit complete.

 

 

 

查看删除之前的状态:

 

SQL> select * from wwl as of scn 1073555;

 

       ID NAME

---------- --------------------

        1 wwl

        2 wwl

        3 wwl

        4 wwl

        5 wwl

        6 xgx

        7 xgx

        8 xgx

        9 xgx

       10 xgx

 

10 rows selected.

 

 

用FlashbackQuery恢复之前的数据:

 

SQL> insert into wwl select * from wwlas of scn 1073555;

 

10 rows created.

 

SQL> commit;

 

Commit complete.

 

SQL> select * from wwl;

 

       ID NAME

---------- --------------------

        1 wwl

        2 wwl

        3 wwl

        4 wwl

        5 wwl

        6 xgx

        7 xgx

        8 xgx

        9 xgx

       10 xgx

 

10 rows selected.

 

 

实际上,Oracle在内部都是使用scn,即使你指定的是as of timestamp,oracle也会将其转换成scn,系统时间标记与scn之间存在一张表,即SYS下的SMON_SCN_TIME

 

 

SQL> desc sys.smon_scn_time

 

 名称                      是否为空? 类型

 

 -------------------------------------------------    ---------------------------

 

 

 THREAD                               NUMBER

 

 TIME_MP                              NUMBER

 

 TIME_DP                              DATE

 

 SCN_WRP                             NUMBER

 

 SCN_BAS                              NUMBER

 

 NUM_MAPPINGS                       NUMBER

 

 TIM_SCN_MAP                         RAW(1200)

 

 SCN                                   NUMBER

 

 ORIG_THREAD                         NUMBER

 

 

每隔5 分钟,系统产生一次系统时间标记与scn 的匹配并存入sys.smon_scn_time表,该表中记录了最近1440个系统时间标记与scn的匹配记录,由于该表只维护了最近的1440 条记录,因此如果使用as of timestamp的方式则只能flashback 最近5天内的数据(假设系统是在持续不断运行并无中断或关机重启之类操作的话)。

 

注意理解系统时间标记与scn的每5 分钟匹配一次这句话,举个例子,比如scn:339988,339989分别匹配08-05-3013:52:00 和2008-13:57:00,则当你通过as of timestamp查询08-05-30 13:52:00 或08-05-30 13:56:59这段时间点

内的时间时,oracle都会将其匹配为scn:339988 到undo表空间中查找,也就说在这个时间内,不管你指定的时间点是什么,查询返回的都将是08-05-30 13:52:00这个时刻的数据。

 

查看SCN 和 timestamp 之间的对应关系:

select scn,to_char(time_dp,'yyyy-mm-ddhh24:mi:ss')from sys.smon_scn_time;

 

 

 

Flashback version Query

 

 

相对于FlashbackQuery只能看到某一点的对象状态,Oracle 10g引入的Flashback Version Query可以看到过去某个时间段内,记录是如何发生变化的。根据这个历史,DBA就可以快速的判断数据是在什么时点发生了错误,进而恢复到之前的状态。

 

 

先看一个伪列ORA_ROWSCN. 所谓的伪列,就是假的,不存在的数据列,用户创建表时虽然没有指定,但是Oracle为了维护而添加的一些内部字段,这些字段可以像普通文件那样的使用。

 

 

最熟悉的伪列就是 ROWID,它相当于一个指针,指向记录在磁盘上的位置。ORA_ROWSCN是Oracle 10g 新增的,暂且把它看作是记录最后一次被修改时的SCN。 Flashback Version Query就是通过这个伪列来跟踪出记录的变化历史。

 

 

举个例子:

 

SQL> select * from wwl;

 

       ID NAME

---------- --------------------

        1 wwl

        2 wwl

        3 wwl

        4 wwl

        5 wwl

        6 xgx

        7 xgx

        8 xgx

        9 xgx

       10 xgx

 

10 rows selected.

 

SQL> insert into wwl values(11,'test');

 

1 row created.

 

SQL> commit;

 

Commit complete.

 

SQL>

SQL> select ora_rowscn,id,name from wwl;

 

ORA_ROWSCN         ID NAME

---------- ---------- -------------------

  1073941          1 wwl

  1073941          2 wwl

  1073941          3 wwl

  1073941          4 wwl

  1073941          5 wwl

  1073941          6 xgx

  1073941          7 xgx

  1073941          8 xgx

  1073941          9 xgx

  1073941         10 xgx

  1073941         11 test

 

11 rows selected.

 

SQL>

获取更多的历史信息

 

SQL>selectxid,commit_scn,commit_timestamp,operation,undo_sqlfromflashback_transaction_query qwhere q.xidin(select versions_xidfrom wwlversionsbetweenSCN413946and413959);

或者

 

SQL> Selectversions_xid,versions_startscn,versions_endscn,DECODE(versions_operation,'I','Insert','U','Update','D','Delete','Original') "Operation", id from WWL versions between scn minvalueand maxvalue;

 

VERSIONS_XID     VERSIONS_STARTSCN VERSIONS_ENDSCNOperation                ID

---------------- ----------------- ------------------------------- ----------

050023005F010000           1073941                 Insert                   11

0700050073010000           1073499                 Insert                    1

0700050073010000           1073499                 Insert                    2

0700050073010000           1073499                 Insert                    3

0700050073010000           1073499                 Insert                    4

0700050073010000           1073499                 Insert                    5

0700050073010000           1073499                 Insert                    6

0700050073010000           1073499                 Insert                    7

0700050073010000           1073499                 Insert                    8

0700050073010000           1073499                 Insert                    9

0700050073010000           1073499                 Insert                   10

 

11 rows selected.

下面我们来讲下伪列, Flashback Version Query技术其实有很多伪列,但是ORA_ROWSCN是最重要。它记录的是最后一次被修改时的SCN,注意是被提交的修改。如果没有提交,这个伪列不会发生变化。

 

 

 

ORA_ROWSCN 缺省是数据块级别的,也就是一个数据块内的所有记录都是一个ORA_ROWSCN,数据块内任意一条记录被修改,这个数据库块内的所有记录的ORA_ROWSCN都会同时改变。上例的查询结果以证明。

 

 

不过我们可以在建表时使用关键字 rowdependencies,可以改变这种缺省行为,使用这个关键字后,每条记录都有自己的ORA_ROWSCN。

 

 

举例:

 

SQL> create table wwl2 (idnumber(3))rowdependencies;

 

Table created.

 

SQL> insert into wwl2 values(1);

 

1 row created.

 

SQL> insert into wwl2 values(2);

 

1 row created.

 

SQL> insert into wwl2 values(3);

 

1 row created.

 

SQL> commit;

 

Commit complete.

 

SQL> select ora_rowscn,id from wwl2;

 

ORA_ROWSCN         ID

---------- ----------

  1074533          1

  1074533          2

  1074533          3

 

SQL>

此处SCN一样,一定很奇怪,这正好说明是最后一次被修改时的SCN,如果没有提交,是不会变的,我们重做一下就清楚了。

 

SQL> analyze table wwl computestatistics;

 

Table analyzed.

 

SQL> select ora_rowscn, id from wwl2;

 

ORA_ROWSCN         ID

---------- ----------

  1074533          1

  1074533          2

  1074533          3

 

SQL> delete from wwl2;

 

3 rows deleted.

 

SQL> select ora_rowscn, id from wwl2;

 

no rows selected

 

SQL> insert into wwl2 values(1);

 

1 row created.

 

SQL> commit;

 

Commit complete.

 

 

SQL> insert into wwl2 values(2);

 

1 row created.

 

SQL> commit;

 

Commit complete.

 

SQL> select ora_rowscn, id from wwl2;

 

ORA_ROWSCN         ID

---------- ----------

   1074586          1

  1074596          2

 

SQL>

 

 

Flashback Transaction Query

 

Flashback Transaction Query也是使用UNDO信息来实现。利用这个功能可以查看某个事务执行的所有变化,它需要访问flashback_transaction_query视图,这个视图的XID列代表事务ID,利用这个ID可以区分特定事务发生的所有数据变化。

 

示例:

 

SQL> insert into wwl2 values(3);

 

1 row created.

 

SQL> commit;

 

Commit complete.

 

SQL> select * from wwl2;

 

       ID

----------

        1

        2

        3

 

SQL>

 

查看视图,每个事务都对应相同的XID

 

 

selectxid,commit_scn,commit_timestamp,operation,undo_sqlFROMflashback_transaction_query qwhere q.xidin(select versions_xidfrom wwl2versionsbetweenscn413946and413959);

或者

 

 

SQL> Select xid,operation,commit_scn,undo_sql fromflashback_transaction_query where xid in (SELECT versions_xid from wwl2versions between scn minvalue and maxvalue);

 

XID              OPERATION                                                       COMMIT_SCN UNDO_SQL

-------------------------------------------------------------------------------- ----------------------------------------------------------------------

0100100059010000 INSERT                                                             1074641 delete from "WWL"."WWL2" where ROWID ='AAAMttAAFAAAAAUAAF';

0100100059010000 BEGIN                                                              1074641

0200020063010000 INSERT                                                             1074586 delete from "WWL"."WWL2" where ROWID ='AAAMttAAFAAAAAUAAD';

0200020063010000 DELETE                                                             1074586 insert into "WWL"."WWL2"("ID")values ('3');

0200020063010000 DELETE                                                              1074586 insert into"WWL"."WWL2"("ID") values ('2');

0200020063010000 DELETE                                                             1074586 insert into "WWL"."WWL2"("ID")values ('1');

0200020063010000 BEGIN                                                              1074586

0800210060010000 INSERT                                                             1074596 delete from "WWL"."WWL2" where ROWID ='AAAMttAAFAAAAAUAAE';

0800210060010000 BEGIN                                                               1074596

0800290060010000 INSERT                                                             1074533 delete from "WWL"."WWL2" where ROWID ='AAAMttAAFAAAAAUAAC';

0800290060010000 INSERT                                                              1074533 delete from"WWL"."WWL2" where ROWID = 'AAAMttAAFAAAAAUAAB';

 

XID              OPERATION                                                       COMMIT_SCN UNDO_SQL

-------------------------------------------------------------------------------- ----------------------------------------------------------------------

0800290060010000 INSERT                                                             1074533 delete from "WWL"."WWL2" where ROWID ='AAAMttAAFAAAAAUAAA';

0800290060010000 BEGIN                                                              1074533

 

13 rows selected.

 

注意SYS用户不支持闪回

 

 

 

Flashback Table也是使用UNDO tablespace的内容来实现对数据的回退。该命令相对简单,输入:flashbacktable table_name to scn(to timestamp) 即可。

 

 

注意:如果想要对表进行flashback,必须允许表的rowmovement.

 

Alter table table_name row movement;

 

 

 

要查看某表是否启用rowmovement,可以到user_tables中查询(或all_tables,dba_tables),

 

例如:

SQL> select row_movement fromuser_tables where table_name='WWL2';

ROW_MOVE

--------

ENABLED

 

 

要启用或禁止某表row movement,可以通过下列语句:

 

 

--启用

JSSWEB> ALTER TABLE table_name ENABLEROW MOVEMENT;

表已更改。

--禁止

JSSWEB> ALTER TABLE table_name DISABLEROW MOVEMENT;

表已更改。

 

举例:

 

SQL> create table wwl3 (id number(3));

 

Table created.

 

SQL> insert into wwl3 values(1);

 

1 row created.

 

SQL> insert into wwl3 values(2);

 

1 row created.

 

SQL> commit;

 

Commit complete.

 

SQL> select * from wwl3;

 

       ID

----------

        1

        2

 

SQL> select sysdate from dual;

 

SYSDATE

------------

01-APR-12

 

SQL> alter session setnls_date_format="yyyy-mm-dd hh24:mi:ss";

 

Session altered.

 

SQL> select sysdate from dual;

 

SYSDATE

-------------------

2012-04-01 17:20:40

 

SQL> select current_scn from v$database;

 

CURRENT_SCN

-----------

   1075150

 

SQL>

 

删除数据并恢复

 

SQL> delete from wwl3;

 

2 rows deleted.

 

SQL> commit;

 

Commit complete.

 

SQL> alter table wwl3 enable rowmovement;

 

Table altered.

 

SQL> select row_movement fromuser_tables where table_name='WWL3';

 

ROW_MOVEMENT

----------------

ENABLED

 

SQL>

SQL> flashback table wwl3 to scn1075150;

 

Flashback complete.

 

或者:

 

SQL> flashback table wwl3 to timestampto_timestamp('2012-04-01 17:20:40','yyyy-mm-

 

dd hh24:mi:ss');

 

 

SQL> select * from wwl3;

 

       ID

----------

        1

        2

 

SQL>

Flashbacktable命令支持同时操作多个表,表名中间以逗号分隔即可,如果你执行一条flashback table命令时同时指定了多个表,要记住单个flashbacktable是在同一个事务中,因此这些表的恢复操作要么都成功,要么都失败。

 

如:

 

flashback table wwl1,wwl2,wwl3 to scn 1103864;

 

 

 

一些注意事项:

 

1. 基于undo的表恢复,需要注意DDL 操作的影响第三个就是修改并提交过数据之后,对表做过DDL操作,包括:

drop/modify 列, move表, drop 分区(如果有的话),truncate table/partition,这些操作会另undo表空间中的撤销数据失效,对于执行过这些操作的表应用flashback query会触发ORA-01466 错误。另外一些表结构修改语句虽然并不会影响到undo表空间中的撤销记录,但有可能因表结构修改导致undo 中重做记录无法应用的情况,比如对于增加了约束,而flashback query查询出的undo 记录已经不符合新建的约束条件,这个时候直接恢复显然不可能成功,你要么暂时disable约束,要么通过适当逻辑,对要恢复的数据进行处理之后,再执行恢复。

另外,flashbackquery对v$tables,x$tables等动态性能视图无效,不过对于dba_*,all_*,user_*等数据字典是有效的。同时该特性也完全支持访问远端数据库,比如select* from tbl@dblink as of scn 360;的形式。

 

 

 

2. 基于undo的表恢复,flashbacktable 实际上做的也是dml操作(会在被操作的表上加dml锁),因此还需要注意triggers对其的影响,默认情况下,flashback table toscn/timestamp在执行时会自动disable掉与其操作表相差的triggers,如果你希望在此期间trigger能够继续发挥做用,可以在flashback table 后附加

ENABLE TRIGGERS

 

 

 

补充:

 

 

什么是AutomaticUndo Management(自动撤销管理表空间)

提到自动撤销管理表空间,就不得不提手动管理的回滚段。在9i之前,回滚段的管理和监控是需要dba手工介入的,创建合适的回滚段是件非常耗费dba精力的事情,你可能需要不断关注oracle 运行状况很长一阵子时间后,通过不断的调整才能基本确认一段时期内回滚段的大小,一旦回滚段创建的不合适,就极有可能引起性能问题甚至错误,比如ora-1555就是典型的回滚段设置不合适触发的。

9i 之后呢(含9i),oracle为了清晰它的整个概念,取消了回滚段这个说法(实际上并未取消回滚段),而完全以undo来代替,这也它正好与redo 相对应,一个重做,一个撤销。回滚段可以不再由dba手工介入,而是完全由它自己在运行时自动分配,这在一定程度上即解放了dba,也确实起到了提高性能的作用,比如采用自动管理表空间就可以最大程序的降低ora-1555发生的机率(注意是降低,不是避免,我们不可能创建一个无限大的回滚段,ora-1555也并不完全是回滚段造成的,关于ora-1555 的问题这里就不深入讨论了,互联网上已经有太多文章描述和介绍该问题及解决方案)

 

是否起用自动管理的撤销表空间由二个初始化参数决定:

UNDO_MANAGEMENT:值为AUTO表示使用了自动撤销管理表空间,MANUAL 则表示手动管理

UNDO_TABLESPACE:当UNDO_MANAGEMENT值为AUTO 时,该参数用来指定当前的undo表空间名称。

undo 表空间的大小,直接影响到flashback query的查询能力,因为多版本查询所依赖的undo 数据都存储在undo表空间中,该表空间越大,所能够存储的undo 数据自然也越多,如果该表空间可用空间非常小,别说flashback了,恐怕正常查询都有可能触发ora-1555 吧。

 

 

初始化参数UNDO_RETENTION

该参数用来指定undo记录保存的最长时间,以秒为单位,是个动态参数,完全可以在实例运行时随时修改通常默认是900秒,也就是15 分钟。

一定要注意,undo_retention只是指定undo数据的过期时间,并不是说,undo 中的数据一定会在undo表空间中保存15分钟,比如说刚一个新事务开始的时候,如果undo 表空间已经被写满,则新事务的数据会自动覆盖已提交事务的数据,而不管这些数据是否已过期,因此呢,这就又关联回了第一点,当你创建

一个自动管理的undo表空间时,还要注意其空间大小,要尽可能保证undo 表空间有足够的存储空间。

同时还要注意,也并不是说,undo_retention中指定的时间一过,已经提交事务中的数据就立刻无法访问,它只是失效,只要不被别的事务覆盖,它会仍然存在,并可随时被flashback特性引用。如果你的undo表空间足够大,而数据库又不是那么繁忙,那么其实undo_retention参数的值并不会影响到你,哪怕你设置成1,只要没有事务去覆盖undo数据,它就会持续有效。因此呢,这里还是那句话,要注意undo表空间的大小,保证其有足够的存储空间。

 

 

只有在一种情况下,undo表空间能够确保undo 中的数据在undo_retention指定时间过期前一定有效,就是为undo 表空间指定Retention Guarantee,指定之后,oracle对于undo 表空间中未过期的undo数据不会覆盖,

 

例如:

SQL> Alter tablespace undotbs1 retentionguarantee;

如果想禁止undo表空间retention guarantee,

 

例如:

SQL> Alter tablespace undotbs1 retentionnoguarantee;