为了使Oracle数据库从任何逻辑误操作中迅速地恢复,Oracle推出了闪回技术。该技术首先以 闪回查询 (Flashback Query)出现在 Oracle 9i版本中,后来Oracle在 10g中对该技术进行了全面扩展,提供了 闪回数据库闪回删除闪回表闪回事物闪回版本查询等功能,在 11g 中,Oracle继续对该技术进行改进和增强,增加了 闪回数据归档功能。

在Oracle 11g中,闪回技术包括以下各项。

1 闪回数据库(Flashback Database该特性允许用户通过flashback database语句,使数据库迅速地回滚到以前的某个时间点或者某个SCN(系统更改号)上,而不需要进行时间点的恢复操作。该功能不基于撤销数据(undodata),而是基于闪回日志。

2 闪回丢弃(Flashback Drop类似于操作系统的垃圾回收站功能,可以从中恢复被drop的表或者索引。该功能基于撤销数据(undodata)。

3 闪回版本查询(Flashback Version Query通过该功能,可以看到特定的表在某个时间段内所进行的任何修改操作,如同电影回放一样,表在该时间段内的变化一览无余。该功能基于撤销数据(undodata)。

4 闪回事务查询(Flashback Transaction Query使用该特性,可以在事物级别上检查数据库的任何改变,大大方便了对数据库的性能优化、事务审计及错误诊断等操作。该功能基于撤销数据(undodata)。

5 闪回表(Flashback Table使用该特性,可以确保数据库表能够被恢复到之前的某一个时间点上。注意,该功能与最早的9i中的Flashback Query不同,Flashback Query仅仅是得到了表在之前某个时间点上的快照而已,并不改变当前表的状态;而Falshback Table却能够将表及附属对象一起恢复到以前的某个时间点。该功能基于撤销数据(undodata)。

6 闪回数据归档(Flashback Data Archive通过flashback data archive,可以查询指定对象的任何时间点(只要满足保护策略)的数据,而且不需要利用到undo,这在有审计需要的环境,或者是安全性特别重要的高 可用数据库中,是一个非常好的特性。缺点就是如果该表变化很频繁,对空间的要求可能很高。Flashback data archive是针对对象的保护,是flashback database的一个强力补充。
  

所有的闪回技术,除了闪回数据库,都是基于撤销数据(undodata)。
   闪回数据库技术可以替代 不完全恢复,优势在于闪回数据库更快效率更高,它是基于 闪回日志的(所以需要开启闪回功能alter database flashback on)。

1 闪回数据库(Flashback Database)

闪回数据库概述
闪回数据库能够使数据库迅速回滚到以前的某个时间点或者某个SCN(系统更改号)上。这对于数据库从逻辑错误中恢复特别有用,而且也是大多数逻辑损害时恢复数据库的最佳选择。该功能不基于撤销数据(undodata),而是 基于闪回日志

Oracle系统为了使用数据库的闪回功能,特别创建了另外一组日志,就是Flashback_logs(闪回日志),记录数据库的闪回操作。

使用闪回数据库恢复比使用传统的恢复方法要快得多,这是因为恢复不再受数据库大小的影响。也就是说,传统的恢 复时间(MTTR)是由所需重建的数据文件的大小和所要应用的归档日志的大小决定的。而使用闪回数据库恢复,恢复时间是由恢复过程中需要备份的变化的数量 决定的,而不是数据文件和归档日志的大小。

闪回数据库的结构是由 恢复写入器(RVWR)后台进程和 闪回数据库日志组成的。

如果要启用闪回数据库功能,RVWR 进程也要启动。

闪回数据库日志是一种新的日志文件类型,它包括物理数据块先前的“图像”。

闪回恢复区是闪回数据库的先决条件,因为RVWR进程要将闪回日志写入该区域中,所以在使用闪回数据库功能时,必须要启用该区。

对于逻辑损害和用户的误操作,闪回数据库是不完全恢复的优秀替代。但是必须要指出的是,闪回数据库有其自身的局限性。
局限性:
1 使用闪回数据库恢复不能解决媒介故障。若要从媒介故障中恢复,仍然需要重建数据文件和恢复归档日志文件。
2 截短数据文件(缩小数据文件到较小的尺寸),用闪回数据库不能恢复此类操作。

3 如果控制文件已被重建,不能使用闪回数据库。
4 不能完成删除一个表空间的恢复。
5 最多只能将数据库恢复到在闪回日志中最早可用的那个SCN,并不能将数据库恢复到任意的SCN值。

配置闪回数据库
配置闪回恢复区以后,要启用闪回数据库功能,还需要进行进一步的配置,需要注意如下几点。
l 配置闪回恢复区。
2 数据库需要运行在归档模式下(Archivelog)。
3通过数据库参数DB_FLASHBACK_RETENTION_TARGET,来指定可以在多长时间内闪回数据库。该值以分钟为单位,默认值为1440(1天),更大的值对应更大的闪回恢复空间,类似于闪回数据库的基线。
4 需要在MOUNT状态下使用ALTER DATABASE FLASHBACK ON 命令启动闪回数据库功能。

配置闪回恢复区

DB_RECOVERY_FILE_DEST
这两个参数分别用来指定闪回恢复区的位置与闪回恢复区的大小(默认值为空)。

DB_RECOVERY_FILE_DEST_SIZE
以下通过实例来具体说明,注意在设定这两个动态初始化参数时,不需要重启实例。

SQL> ALTER SYSTEM SET db_recovery_file_dest_size=2g SCOPE=BOTH;

SQL> ALTER SYSTEM SET db_recovery_file_dest='/u01/app/oracle/flash_recovery_area'
SCOPE=BOTH;

当然,也可以通过以下命令来查看修改后的参数是否生效:

SQL> SHOW parameter db_recovery_file_dest

NAME TYPE VALUE


db_recovery_file_dest string /u01/app/oracle/flash_recovery_area

db_recovery_file_dest_size big integer 2G

也有专门的命令来修改闪回恢复区的大小,以及停用闪回恢复区。这些命令都使用ALTER SYSTEM语句来执行,具体如下。

①将闪回恢复区的大小设置为4GB。

SQL> ALTER SYSTEM SET db_recovery_file_dest_size=4g SCOPE=BOTH;

②要停用闪回恢复区,只需将参数db_recovery_file_dest置空就可以了。

SQL>ALTER SYSTEM SET db_recovery_file_dest=’’;

当闪回恢复区中的空间使用率超过85%的时候,数据库将会向alert文件中写入警告信息。而当超过97%的时候将会写入严重告警信息。当闪回恢复区空间全部耗尽的时候,Oracle将报告如下类似的错误:

ORA-19809: limit exceeded for recovery files

ORA-19804: cannot reclaim 52428800 bytes disk space from 1258291200 limit

此时查询视图dba_outstanding_alerts,将会给出错误的原因及操作建议

闪回目录打开的步骤

DB必须是归档的

1:关闭DB
2:mount DB
3:开启闪回日志的功能 alter database flashback on; ----写入控制文件,所以必须mount
4:打开DB alter database open;

1:
SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.

2:
[oracle@chen dbs]$ vim initdb02.ora ---------------让归档目录去OMF自己管理的目录/u01/app/oracle/fast_recovery_area
*.log_archive_start=true
*.log_archive_dest_2='location=/home/oracle/db02_archive1'
*.log_archive_dest_2='location=/home/oracle/db02_archive2'
*.log_archive_format=db02_%t%r_%s.arc

3:
startup mount;
SQL> alter database flashback on;

Database altered.

4:
SQL> alter database open;

Database altered.

SQL> select flashback_on from v$database;

FLASHBACK_ON


YES

[oracle@chen ~]$ cd /u01/app/oracle/fast_recovery_area/DB02/

[oracle@chen DB02]$ ls
archivelog backupset flashback onlinelog

使用闪回database恢复数据的步骤 -----只能对付用户做的误操作,不能解决磁盘坏了

1 关闭DB
shutdown immediate;

2 mount DB
startup mount;

3 执行闪回DB的操作
flashback database to timestamp '时间点';

4 打开DB
alter database open resetlogs;

闪回缓存区,存储日志文件,放在SGA,占用16M的空间

反向的闪回日志

闪回的功能在控制文件中

有进程,内存,I/O开销

案例

1:800 时间点
2:1000
3:破坏
4:恢复

1:基于时间的恢复

SQL> select * from emp001 where empno=7369;

EMPNO ENAME SAL


7369 SMITH 800

SQL> select sysdate from dual;

SYSDATE


2014-06-25 10:57:48

2:
SQL> update emp001 set sal=1000 where empno=7369;

1 row updated.

SQL> commit;

Commit complete.

3:
SQL> drop table emp001 purge;

Table dropped.

SQL> select * from emp001;
select * from emp001
*
ERROR at line 1:
ORA-00942: table or view does not exist

4:恢复
SQL> conn /as sysdba
Connected.

SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.

5:
SQL> startup mount
ORACLE instance started.

Total System Global Area 768294912 bytes
Fixed Size 2232312 bytes
Variable Size 452984840 bytes
Database Buffers 306184192 bytes
Redo Buffers 6893568 bytes
Database mounted.

6:
SQL> flashback database to timestamp '2014-06-25 10:57:48';
flashback database to timestamp '2014-06-25 10:57:48'
*
ERROR at line 1:
ORA-00932: inconsistent datatypes: expected TIMESTAMP got CHAR

失败原因:2014-06-25:09:53:42是date的格式,而不是timestamp的格式;
日期类型和时间类型是两个类型

SQL> flashback database to timestamp to_timestamp('2014-06-25 10:57:48','yyyy-mm-dd hh24:mi:ss');

Flashback complete.

7:
SQL> alter database open resetlogs;

Database altered.

SQL> select * from scott.emp001 where empno=7369;

EMPNO ENAME SAL


7369 SMITH 800

恢复2:基于SCN号的恢复:

如何查看当前的SCN号?

SQL> select current_scn from v$database;

CURRENT_SCN


1051621

SQL> select current_scn from v$database;

CURRENT_SCN


1051621

SQL> conn scott/tiger
Connected.

SQL> drop table emp002 purge;

Table dropped.

SQL> shutdown immediate

SQL> startup mount

SQL> flashback database to scn 1051621;

Flashback complete.

SQL> alter database open resetlogs;

Database altered.

SQL> select * from scott.emp002 where empno=7369;

EMPNO ENAME SAL


7369 SMITH 800

2 闪回丢弃(Flashback Drop)

闪回丢弃是将被丢弃的数据库对象及其相依对象的复制保存在回收站中,以便在必要时能够及时恢复这些对象。在回收站被清空以前,被丢弃的对象并没有从数据库中删除。这就使数据库能够恢复被意外或者误操作而删除的表。

为了更好地理解闪回丢弃,需要理解回收站的工作细节,以及丢弃对象在回收站中的存储、查询与清除等,将在以下的小节中介绍。

回收站概念

回收站(Recycle Bin)是所有丢弃表及其相依对象的逻辑存储容器。当一个表被丢弃时(DROP),回收站会将该表及其相依对象存储在回收站中。存储在回收站中的表的相依对象包括索引、约束、触发器、嵌套表、大的二进制对象(LOB)段和LOB索引段。

Oracle回收站将用户所进行的DROP语句的操作记录在一个系统表里,即将被删除的对象写到一个数据字典表中,确定是不再需要的被删除对象时,可以使用PURGE命令对回收站空间进行清除。
为了避免被删除表与同类对象名称的重复,被删除表(及相依对象)放到回收站中后,Oracle系统对被删除的对象名进行了转换。被删除对象(如表)的名字转换格式如下:BIN$globalUID$version
globalUID是一个全局唯一的、24个字符长的标识对象,它是Oracle内部使用的标识,对于用户来说没有任何实际意义,因为这个标识与对象未删除前的名称没有关系。
$version 是Oracle数据库分配的版本号。

使用回收站

如果要对DROP过的表进行恢复操作,可以使用以下语句:
SQL>FLASHBACK TABLE table_name TO BEFORE DROP

为了帮助读者理解回收站在使用中的操作过程,下面给出较详细的回收站操作步骤。
示例:本例给出数据准备、删除表、查询回收站信息、恢复及查询恢复后的情况。
(1)连接Oracle
[oracle@localhost ~]$ sqlplus scott/tiger
SQL> set line 120;
SQL> set pagesize 50;
SQL> show user;
USER is "SCOTT"
(2)准备数据
SQL> create table my_emp as select * from emp;
Table created.
SQL> select count(*) from my_emp;
COUNT(*)


14
(3)删除表结构
SQL> select * from tab;
TNAME TABTYPE CLUSTERID


BONUS TABLE
DEPT TABLE
EMP TABLE
EMP2 TABLE
MY_EMP TABLE
SALGRADE TABLE
SYS_TEMP_FBT TABLE
7 rows selected.
SQL> drop table my_emp;
Table dropped.
SQL>
(4)删除(DROP)表后的数据字典
SQL> select * from tab;
TNAME TABTYPE CLUSTERID


BIN$POiMOEfPgU3gQAB/AQASlg==$0 TABLE
BONUS TABLE
DEPT TABLE
EMP TABLE
EMP2 TABLE
SALGRADE TABLE
SYS_TEMP_FBT TABLE
7 rows selected.

需要说明的是,当MY_EMP表被删除以后,在数据库回收站里变成了BIN$POiMOEfPgU3gQAB/ AQASlg==$0,version是0。

(5)查看user_recyclebin回收站,可以看到删除的表对应的记录:
SQL> col object_name for a30;
SQL> col original_name for a20;
SQL> select object_name,original_name from user_recyclebin;
OBJECT_NAME ORIGINAL_NAME


BIN$POiMOEfPgU3gQAB/AQASlg==$0 MY_EMP
SQL>

(6)利用user_recyclebin中的记录,使用FLASHBACK从回收站恢复表MY_EMP:
SQL> flashback table my_emp to before drop;
Flashback complete.

SQL> select count(*) from my_emp;
COUNT(*)


14
以上是恢复完成后的查询结果。

回收站与空间利用
回收站是丢弃对象的逻辑存储容器,它以表空间中现有的已经分配的空间为基础,这意味着系统并没有给回收站预留空间。这使回收站空间依赖于现有表空间中的可用空间(也就是说丢弃表占据的空间仍然需要计入表空间配额)。因此并不能总是保证丢弃对象在回收站中的最小时间。
如果不对回收站进行清除操作,丢弃对象会一直保存在回收站内,一直到丢弃对象所属的表空间无法再分配新的存储区域,这种状态称之为空间压力。有时,用户的表空间限额也会导致空间压力状态的出现,即使表空间中仍然存在自由空间。
当空间压力出现时,Oracle会覆盖些回收站对象从而自动回收表空间。Oracle根据先进先出的原则来选择丢弃对象进行删除,所以最先被丢弃的对象也最先被清除。而对象的清除仅仅是为了解决产生的空间压力问题,所以会尽可能清除少的对象来满足空间压力的要求。这样处理,既最大限度地保证了对象在回收站中的可用时间,又减少了Oracle在事物处理时的性能影响。
DBA需要关注回收站的空间利用情况,掌握清除回收站对象从而释放空间的办法,这可用PURGE命令来完成。PURGE命令可从回收站中删除表或索引,并释放有关表和索引所占用的空间;用PURGE命令也可清除整个回收站或清除被删除的表空间的所有部分。
值得一提的是,当用PURGE命令清除掉被删除的对象后,该对象确实是被完全清除掉而不能再重建了。

要清除回收站中的对象,释放空间,有以下几种方式。
(1)使用PURGE TABLE original_table_name。
这里的original_table_name表示表在drop以前的名称(源名称),使用该操作可以从回收站中永久地删除对象并释放空间。
(2)使用PURGE TABLE recyclebin_object_name。
这里的recyclebin_object_name表示回收站中的对象名称,使用该操作可以从回收站中永久地删除对象并释放空间。
(3)使用PURGE TABLESPACE tablespace_name从回收站清除一个特定表空间的所有对象。
该命令从指定的表空间中清除所有的丢弃对象及相依对象。因为相依对象(比如LOB、嵌套表、索引和分区等)未必与基表存储在同一个表空间,该命令会将相依对象从其所在的表空间中进行清除。
(4)使用PURGE TABLESPACE tablespace_name USER user_name,会从回收站中清除属于某个特定用户的所有丢弃对象(当然也包括基表的相依对象)。
(5)使用命令DROP USER user_name CASCADE直接删除指定用户及其所属的全部对象。
也就是说DROP USER命令会绕过回收站直接进行删除。同时,如果回收站中也有该用户的所属对象,
则也会从回收站中清除掉。
(6)使用PURGE RECYCLEBIN 命令可以清除用户自己的回收站。
该命令从用户回收站中清除所有的对象并释放与这些对象关联的空间。
(7)PURGE DBA_RECYCLEBIN从所有用户的回收站清除所有对象。
该命令能高效地完全清空回收站,当然执行该命令必须具有SYSDBA系统管理权限才可以。
示例:查询当前用户回收站中的内容,再用PURGE清除。
SQL> show user;
USER is "SCOTT"
SQL> create table orcltest as select * from emp;
Table created.
SQL> select * from tab;
TNAME TABTYPE CLUSTERID


BONUS TABLE
DEPT TABLE
EMP TABLE
EMP2 TABLE
MY_EMP TABLE
ORCLTEST TABLE
SALGRADE TABLE
SYS_TEMP_FBT TABLE
8 rows selected.

SQL> drop table orcltest;
Table dropped.

SQL> select object_name,original_name from user_recyclebin;
OBJECT_NAME ORIGINAL_NAME


BIN$POiMOEfQgU3gQAB/AQASlg==$0 ORCLTEST

SQL> select object_name,original_name from user_recyclebin;
OBJECT_NAME ORIGINAL_NAME


BIN$POiMOEfQgU3gQAB/AQASlg==$0 ORCLTEST

SQL> purge table orcltest;
Table purged.

SQL> select object_name,original_name from user_recyclebin;
no rows selected

恢复drop的表

方法一:
SQL> select * from t3;

ID QQ


1 1
2 2

SQL> drop table t3;

Table dropped.

SQL> select original_name,operation,droptime from recyclebin;

ORIGINAL_NAME OPERATION DROPTIME


T3 DROP 2014-08-24:01:21:23

SQL> flashback table t3 to before drop;

Flashback complete.

SQL> select * from t3;

ID QQ


1 1
2 2
方法二:
SQL> drop table t3;

Table dropped.

SQL> select * from tab;

TNAME TABTYPE CLUSTERID


BIN$AU/tyVw+qJzgUKjAtQFG6g==$0 TABLE
SYS_TEMP_FBT TABLE
T2 TABLE

SQL> select object_name,ORIGINAL_NAME from user_recyclebin;

OBJECT_NAME ORIGINAL_NAME


BIN$AU/tyVw+qJzgUKjAtQFG6g==$0 T3

SQL> create table t4 as select * from "BIN$AU/tyVw+qJzgUKjAtQFG6g==$0";

Table created.

SQL> select * from t4;

ID QQ


1 1
2 2

  假如删除一个表且不放到回收站中不能进行恢复,在drop语句中可以利用purge选项。

Oracle在10g可以在DROP表之后通过简单的命令将表恢复到删除以前的状态。这个命令就是FLASHBACK TABLE。这个功能和WINDOWS的回收站功能很想,而对应的清除回收站的功能就是PURGE。
也就是说FLASHBACK语句会还原最后放入回收站的表,而PURGE语句会清除最早进入回收站的表。
当回收站中存在同名对象的时候,可以用回收站中的名字进行清除和还原。另外FLASHBACK还有RENAME TO语句,可以在还原的时候对表进行重命名,避免和当前用户下已经存在的表冲突。

前两天偶然发现,虽然用户内的表名不能重复,但是由于回收站中给删除表重新起了名字,因此回收站可以包括多个同名表的删除结果。而清空回收站所使用的命令PURGE TABLE TABLENAME,其中TABLENAME是原来的表名,那么当出现重名时,将会清除或还原哪张表?

SQL> show user
USER is "CHEN"

SQL> create table t(id number);

Table created.

SQL> drop table t;

Table dropped.

SQL> create table t(name varchar2(30));

Table created.

SQL> drop table t;

Table dropped.

SQL> col original_name for a8

SQL> select object_name,original_name,droptime from recyclebin;
OBJECT_NAME ORIGINAL DROPTIME


BIN$AU/tyVw+qJzgUKjAtQFG6g==$0 T3 2014-08-24:01:26:14
BIN$AU/tyVxAqJzgUKjAtQFG6g==$0 T 2014-08-24:01:52:05
BIN$AU/tyVw/qJzgUKjAtQFG6g==$0 T 2014-08-24:01:51:24

SQL> desc t
ERROR:
ORA-04043: object t does not exist

SQL> flashback table t to before drop;

Flashback complete.

SQL> desc t
Name Null? Type


NAME VARCHAR2(30)

结论:也就是说FLASHBACK语句会还原最后放入回收站的表,而PURGE语句会清除最早进入回收站的表。

SQL> flashback table "BIN$AU/tyVw/qJzgUKjAtQFG6g==$0" to before drop rename to tt;

Flashback complete.

SQL> desc tt
Name Null? Type


ID NUMBER

 

3 闪回版本查询

在 Oracle9i Database 中,我们看到它推出了以闪回查询形式表示的“时间机器”。该特性允许 DBA 看到特定时间的列值,只要在还原段中提供该数据块此前镜像的拷贝即可。但是,闪回查询只提供某时刻数据的固定快照,而不是在两个时间点之间被更改数据的运行状态表示。某些应用程序,如涉及到外币管理的应用程序,可能需要了解一段时期内数值数据的变化,而不仅仅是两个时间点的数值。由于闪回版本查询特性,Oracle Database 10g 能够更方便高效地执行该任务。

在 Oracle9i Database 中,我们看到它推出了以闪回查询形式表示的“时间机器”。该特性允许 DBA 看到特定时间的列值,只要在还原段中提供该数据块此前镜像的拷贝即可。但是,闪回查询只提供某时刻数据的固定快照,而不是在两个时间点之间被更改数据的运行状态表示。某些应用程序,如涉及到外币管理的应用程序,可能需要了解一段时期内数值数据的变化,而不仅仅是两个时间点的数值。由于闪回版本查询特性,Oracle Database 10g 能够更方便高效地执行该任务。

查询对表的更改

在本示例中,我使用了一个银行外币管理应用程序。其数据库含有一个名称为 RATES 的表,用于记录特定时间的汇率。

SQL> desc rates
Name Null?Type


CURRENCY VARCHAR2(4)
RATE NUMBER(15,10)

该表显示 US$ 与各种其他货币的汇率,在 CURRENCY 列中显示。在金融服务行业中,汇率不但在变更时进行更新,而且被记录在历史中。需要这种方式的原因是银行交易可能在“过去时间”生效,以便适应由于汇款而耗费的时间。例如,对于一项在上午 10:12 发生但在上午 9:12 生效的交易,其有效汇率是上午 9:12 的汇率,而不是现在的汇率。

直到现在,唯一的选择是创建一个汇率历史表来存储汇率的变更,然后查询该表是否提供历史记录。另一种选择是在 RATES 表本身中记录特定汇率适用性的开始和结束时间。当发生变更时,现有行中的 END_TIME 列被更新为 SYSDATE,并插入一个具有新汇率的新行,其 END_TIME 为 NULL。

但是在 Oracle Database 10g 中,闪回版本查询特性不需要维护历史表或存储开始和结束时间。使用该特性,您不必进行额外的设置,即可获得某行在过去特定时间的值。

例如,假定该 DBA 在正常业务过程中数次更新汇率 — 甚至删除了某行并重新插入该行:

insert into rates values ('EURO',1.1012);
commit;
update rates set rate = 1.1014;
commit;
update rates set rate = 1.1013;
commit;
delete rates;
commit;
insert into rates values ('EURO',1.1016);
commit;
update rates set rate = 1.1011;
commit;

在进行了这一系列操作后,DBA 将通过以下命令获得 RATE 列的当前提交值

SQL> select * from rates;

CURR RATE


EURO 1.1011

此输出显示 RATE 的当前值,没有显示从第一次创建该行以来发生的所有变更。这时使用闪回查询,您可以找出给定时间点的值;但我们对构建变更的审计线索更感兴趣 — 有些类似于通过便携式摄像机来记录变更,而不只是在特定点拍摄一系列快照。

以下查询显示了对表所做的更改:

select versions_starttime, versions_endtime, versions_xid,
versions_operation, rate
from rates versions between timestamp minvalue and maxvalue
order by VERSIONS_STARTTIME
/

VERSIONS_STARTTIME VERSIONS_ENDTIME VERSIONS_XID V RATE


01-DEC-03 03.57.12 PM 01-DEC-03 03.57.30 PM 0002002800000C61 I 1.1012
01-DEC-03 03.57.30 PM 01-DEC-03 03.57.39 PM 000A000A00000029 U 1.1014
01-DEC-03 03.57.39 PM 01-DEC-03 03.57.55 PM 000A000B00000029 U 1.1013
01-DEC-03 03.57.55 PM 000A000C00000029 D 1.1013
01-DEC-03 03.58.07 PM 01-DEC-03 03.58.17 PM 000A000D00000029 I 1.1016
01-DEC-03 03.58.17 PM 000A000E00000029 U 1.1011

注意,此处显示了对该行所作的所有更改,甚至包括该行被删除和重新插入的情况。VERSION_OPERATION 列显示对该行执行了什么操作 (Insert/Update/Delete)。所做的这些工作不需要历史表或额外的列。

在上述查询中,列 versions_starttime、versions_endtime、versions_xid、versions_operation 是伪列,与 ROWNUM、LEVEL 等其他熟悉的伪列相类似。其他伪列 — 如 VERSIONS_STARTSCN 和 VERSIONS_ENDSCN — 显示了该时刻的系统更改号。列 versions_xid 显示了更改该行的事务标识符。有关该事务的更多详细信息可在视图FLASHBACK_TRANSACTION_QUERY 中找到,其中列 XID 显示事务 id。例如,使用上述的 VERSIONS_XID 值 000A000D00000029,UNDO_SQL 值显示了实际的语句。

注: versions_starttime : 这个数据开始生效的时间
VERSIONS_ENDTIME :这个数据失效的时间--一般就是下面一条记录开始的时间
versions_xid : 显示了更改该行的事务标识符。
VERSION_OPERATION :这条记录执行的操作(Insert/Update/Delete)

SELECT UNDO_SQL
FROM FLASHBACK_TRANSACTION_QUERY
WHERE XID = '000A000D00000029';

UNDO_SQL

insert into "ANANDA"."RATES"("CURRENCY","RATE") values ('EURO','1.1013');

除了实际语句之外,该视图还显示提交操作的时间标记和 SCN、查询开始时的 SCN 和时间标记以及其他信息。

找出一段时期中的变更

现在,让我们来看如何有效地使用这些信息。假设我们需要找出下午 3:57:54 时 RATE 列的值。我们可以执行:

select rate, versions_starttime, versions_endtime
from rates versions
between timestamp
to_date('12/1/2003 15:57:54','mm/dd/yyyy hh24:mi:ss')
and to_date('12/1/2003 16:57:55','mm/dd/yyyy hh24:mi:ss')
/

RATE VERSIONS_STARTTIME VERSIONS_ENDTIME


1.1011

此查询与闪回查询类似。在以上的示例中,开始和结束时间为空,表示汇率在该时间段中没有更改,而是包含一个时间段。还可以使用 SCN 来找出过去的版本值。可以从伪列 VERSIONS_STARTSCN 和 VERSIONS_ENDSCN 中获得 SCN 号。以下是一个示例:

select rate, versions_starttime, versions_endtime
from rates versions
between scn 1000 and 1001
/

使用关键词 MINVALUE 和 MAXVALUE,可以显示还原段中提供的所有变更。您甚至可以提供一个特定的日期或 SCN 值作为范围的一个端点,而另一个端点是文字 MAXVALUE 或 MINVALUE。例如,以下查询提供那些只从下午 3:57:52 开始的变更,而不是全部范围的变更:

select versions_starttime, versions_endtime, versions_xid,
versions_operation, rate
from rates versions between timestamp
to_date('12/11/2003 15:57:52', 'mm/dd/yyyy hh24:mi:ss')
and maxvalue
order by VERSIONS_STARTTIME
/

VERSIONS_STARTTIME VERSIONS_ENDTIME VERSIONS_XID V RATE


01-DEC-03 03.57.55 PM 000A000C00000029 D 1.1013
01-DEC-03 03.58.07 PM 01-DEC-03 03.58.17 PM 000A000D00000029 I 1.1016
01-DEC-03 03.58.17 PM 000A000E00000029 U 1.1011

最终的分析

闪回版本查询随取随用地复制表变更的短期易变数值审计。这一优点使得 DBA 能够获得过去时间段中的所有变更而不是特定值,只要还原段中

提供数据,就可以尽情使用。因此,最大的可用版本依赖于 UNDO_RETENTION 参数。

注: 暂未大规模使用过,不知道该操作对性能以及磁盘的开销影响有多大?

4 闪回事务查询

闪回事务查询有别于闪回查询的特点有以下3个:

(1)其正常工作不但需要利用撤销数据,还需要事先启用最小补充日志。

(2)返回的结果不是以前的“旧”数据,而是能够将当前数据修改为以前的样子的撤销SQL(Undo SQL)语句。

(3)集中地在名为flashback_transaction_query表上查询,而不是在各个表上通过“as of”或“versions between”子句查询。

了解了以上特点之后,使用闪回事务查询就没有任何困难了,首先打开 最小补充日志

SQL> alter database add supplemental log data;

Database altered.

从此以后,只要在闪回查询的查询窗口内,管理员就可以通过flashback_transaction _query表获得相关事务的撤销SQL。下面列举一个典型的闪回事务查询的使用方法。

场景:用户在一个事务中分别使用insert和update命令修改了hr.departments和hr.employees表,命令细节如下所示:

SQL> insert into hr.departments
2 (department_id,department_name,manager_id,location_id)
3 values (999,'SETI',100,1700);

1 row created.

SQL> update hr.employees set department_id=999
2 where employee_id=200;

1 row updated.

SQL> commit;

Commit complete.

该事务创建了一个新的999号部门,并且将200号员工指派入该新部门,该员工在此之前在10号部门上班。可惜这个事务是人为错误!且看如何利用闪回事务查询恢复原始状态。首先通过闪回版本查询获得该事务的XID,比如从错误的999号部门入手:

SQL> select
2 versions_xid,versions_startscn,department_id,department_name
3 from hr.departments
4 versions between timestamp minvalue and maxvalue
5 where department_id=999
6 order by 2 nulls first;

VERSIONS_XID VERSIONS_STARTSCN DEPARTMENT_ID DEPARTMENT_NAME


090010002B030000 1037789 999 SETI

然后使用结果中的事务号090010002B030000查询flashback_transaction_query表以获得撤销SQL:

SQL> select undo_sql
2 from flashback_transaction_query
3 where xid='090010002B030000';

UNDO_SQL

update "HR"."EMPLOYEES" set "DEPARTMENT_ID" = '10'
where ROWID = 'AAAR5pAAFAAAADLAAC';

delete from "HR"."DEPARTMENTS"
where ROWID = 'AAAR5kAAFAAAACtAAA';

2 rows selected.

结果得到了两句dml命令,如果遵循给出的ROWID不难发现撤销SQL试图将hr.employees表中200号员工的部门从999修改为10:

SQL> select employee_id,department_id
2 from hr.employees where rowid='AAAR5pAAFAAAADLAAC';

EMPLOYEE_ID DEPARTMENT_ID


200 999

并且试图删除999号部门:

SQL> select * from hr.departments where ROWID = 'AAAR5kAAFAAAACtAAA';

DEPARTMENT_ID DEPARTMENT_NAME MANAGER_ID LOCATION_ID


999 SETI 100 1700

如果根据撤销SQL的手段处理,那不是正好将一开始的新部门创建及修改200号员工部门的insert和update命令抵消。笔者利用一个简单的PL/SQL匿名块来执行undo_sql:

SQL> begin
2 for rec in
3 (select undo_sql
4 from flashback_transaction_query
5 where xid='090010002B030000')
6 loop
7 if rec.undo_sql is not null then
8 execute immediate substr(rec.undo_sql,1,length(rec.undo_sql)-1);
9 end if;
10 end loop;
11 commit;
12 end;
13 /

PL/SQL procedure successfully completed.

检查一下效果,应该发现200号员工不在999号部门了:

SQL> select department_id from hr.employees where employee_id=200;

DEPARTMENT_ID


10

并且999号部门也不存在了:

SQL> select department_name from hr.departments where department_id=999;

no rows selected

闪回事务查询可以将同一事务的所有撤销SQL列出,这是闪回查询做不到的,如有必要,管理员还能够执行对应一个事务的部分撤销SQL以一种破坏事务原子性的方式恢复一部分数据,如此行事正确与否完全取决于应用的逻辑。

最后,因为ddl命令的撤销SQL包括对数据字典表的DML操作,并且人为地直接修改数据字典表是非常危险的,况且某些DDL操作不仅仅是对数据字典的DML操作,它们还涉及撤销SQL无法影响到的领域,所以不要指望通过直接执行撤销SQL恢复错误的ddl命令造成的影响。

5 闪回表(Flashback Table),闪回查询

一: 闪回查询 Falshback query ,恢复delete删除数据
  Oracle Flashback Table特性利用Flashback Table语句,确保闪回到表的前一个时间点。与Oracle 9i中的Flashback Query相似,利用回滚段信息来恢复一个或一些表到以前的一个时间点(一个快照)。要注重的是,Flashback Table不等于Flashback Query,Flashback Query仅仅是查询以前的一个快照点而已,并不改变当前表的状态,而Flashback Table将改变当前表及附属对象一起回到以前的时间点。

SQL> grant flashback any table to chen;

SQL> select log_mode,open_mode,flashback_on from v$database;

LOG_MODE OPEN_MODE FLASHBACK_ON


ARCHIVELOG READ WRITE NO -------------- 不需要开启闪回功能

SQL> select * from t2;

ID QQ


1 1
2 2

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

TO_CHAR(SYSDATE,'YY


2014-08-24 00:13:29

SQL> delete t2;

2 rows deleted.

SQL> commit;

Commit complete.

SQL> select * from t2;

no rows selected

1 闪回查询
SQL> select * from t2 as of timestamp to_timestamp('2014-08-24 00:13:59', 'yyyy-mm-dd hh24:mi:ss');

ID QQ


1 1
2 2

2 恢复delete删除的数据
方法一:
SQL> create table t3 as select * from t2 as of timestamp to_timestamp('2014-08-24 00:13:59', 'yyyy-mm-dd hh24:mi:ss');

Table created.

SQL> select * from t3;

ID QQ


1 1
2 2

方法二:
SQL> select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from dual;

TO_CHAR(SYSDATE,'YY


2014-08-24 01:04:13

SQL> delete t3 where id=2;

1 row deleted.

SQL> commit;

Commit complete.
SQL> select * from t3;

ID QQ


1 1

SQL> alter table chen.t3 enable row movement;

Table altered.
----------------- 被flashback回来rowid发生了变化,这也是为什么flashback table 需要enable row movement的原因,正常情况表中 数据的rowid是不绝对不可以改变的;

SQL> flashback table chen.t3 to timestamp to_timestamp('2014-08-24 01:04:13','yyyy-mm-dd hh24:mi:ss');

Flashback complete.

SQL> select * from t3;

ID QQ


1 1
2 2

注:推荐使用scn,由于oracle9i中,因为scn与时间点的同步需要5分钟,如果最近5分钟之内的数据需要Falshback query查询,可能会查询丢失,而scn则不存在这个问题。Oracle10g中这个问题已修正(scn与时间点的大致关系,可以通过logmnr分析归档日志获得)。
方法三:
SQL> select current_scn from v$database;
CURRENT_SCN


1078776
SQL> delete t4;
3 rows deleted.
SQL> select * from t4;
no rows selected

SQL> alter table chen.t4 enable row movement;
Table altered.
SQL> flashback table chen.t4 to scn 1078706;
Flashback complete.
SQL> select * from t4;
ID QQ


1 1
2 2
3 3

注:推荐使用scn,由于oracle9i中,因为scn与时间点的同步需要5分钟,如果最近5分钟之内的数据需要Falshback query查询,可能会查询丢失,而scn则不存在这个问题。Oracle10g中这个问题已修正(scn与时间点的大致关系,可以通过logmnr分析归档日志获得)。

Falshback query查询的局限:
1.不能Falshback到5天以前的数据。
2.闪回查询无法恢复到表结构改变之前,因为闪回查询使用的是当前的数据字典。
3.受到undo_retention参数的影响,对于undo_retention之前的数据,Flashback不保证能Flashback成功。
4.对drop,truncate等不记录回滚的操作,不能恢复。
5.普通用户使用dbms_flashback包,必须通过管理员授权。命令如下:
SQL>grant execute on dbms_flashback to scott;

6 闪回数据的归档 11g

从Oracle Database 11g开始,Oracle 提供了一个这样的功能: 闪回数据归档(Flashback Data Archive)。通过这一功能Oracle数据库可以将UNDO数据进行归档,从而提供全面的历史数据查询,也因此 Oracle 引入一个新的概念Oracle Total Recall也即Oracle全面回忆功能。闪回数据归档可以和我们一直熟悉的日志归档类比,日志归档记录的是Redo的历史状态,用于保证恢复的连续性;而闪回归档记录的是UNDO的历史状态,可以用于对数据进行闪回追溯查询;后台进程LGWR用于将Redo信息写出到日志文件,ARCH进程负责进行日志归档;在Oracle 11g中,新增的后台进程FBDA(Flashback Data Archiver Process)则用于对闪回数据进行归档写出:
[oracle@sp3: ~]$ps -ef | grep fbda | grep -v grep
oracle 3251 1 0 Jan07 ? 00:00:11 ora_fbda_ccdb
闪回归档数据甚至可以以年为单位进行保存,Oracle可以通过内部分区和压缩算法减少空间耗用,这一特性对于需要审计以及历史数据分区的环境尤其有用,但是注意,对于繁忙的数据库环境,闪回数据存储显然要耗用更多的存储空间。当然,用户可以根据需要,对部分表进行闪回数据归档,从而满足特定的业务需求。
因为闪回数据归档需要独立的存储,所以在使用该特性之前需要创建独立的ASSM(自动段空间管理)表空间:
sys@TQGZS11G> create tablespace fbda datafile '/oracle/oradata/tqgzs11g/FBDA.dbf' size 200M segment space management auto;
Tablespace created.
然后可以基于该表空间创建闪回数据归档区, FLASHBACK ARCHIVE ADMINISTER系统权限是创建闪回数据存档所必需的,此处使用SYS用户进行:
sys@TQGZS11G> create flashback archive fda tablespace fbda retention 1 month;
Flashback archive created.
此后就可以使用该归档区来记录数据表的闪回数据量。为了测试方便,先将UNDO表空间更改为较小,以使得UNDO数据能够尽快老化:
sys@TQGZS11G> create undo tablespace UNDOTBS2_SMALL datafile '/oracle/oradata/tqgzs11g/UNDOTBS2_SMALL.dbf' size 20M autoextend off;
Tablespace created.
sys@TQGZS11G> alter system set undo_tablespace= UNDOTBS2_SMALL;
System altered.
sys@TQGZS11G> show parameter undo
NAME TYPE VALUE


undo_management string AUTO
undo_retention integer 900
undo_tablespace string UNDOTBS2_SMALL
接下来使用测试用户连接,对测试表执行闪回归档设置, FLASHBACK ARCHIVE对象权限是启用历史数据跟踪所必需的:
转载自chenoracle

最后修改:2022 年 04 月 02 日
如果觉得我的文章对你有用,请随意赞赏