你可能发现表中的数据被不正确的修改了,你可以使用闪回查询来看指定时间的数据。你也可以使用闪回版本查询来查看一段时间所有的改变,闪回版本查询能让你在select后面使用version来指定scn或时间范围,查询也能返回相关元数据,像是事务信息。一旦你看到错误的事务,你可以使用闪回版本查询来标识事务做的改变,使用undo sql来修正这些改变,undo sql是一种修复数据的方法,你也可以使用闪回表可以恢复表到改变之前的状态。

闪回事务查询及闪回表都要在自动undo管理的模式下。

在使用闪回功能之前数据库管理员要做的任务

1创建足够大的undo表空间来保持闪回操作需要的数据,用户更新的数据越多,空间要求的就更多,在administrator'sguid有计算公式(一会找下这个公式)

2启用自动undo管理。

对一个固定大小的undo表空间,oracle自动调整undo retention.对一个自动扩展的undo表空间,oracle保存多于最长查询的undo数据,及undo_retention参数指定的最小阀值。

可以查询v$undostat.tuned_undoretention来决定当前undo表空间需要undo保存的时间。

3指定retention guarantee来确保未过期的undo不会被丢弃。设定undo_retention不是一个强制的限制,如果系统的空间不够,oracle会重写未过期的undo,指定retention gurantee参数来禁止这种行为。

4赋权给使用flashback的用户,角色,

  • For the DBMS_FLASHBACK package, grant the EXECUTE privilege onDBMS_FLASHBACK to provide access to the features in this package.

  • For Flashback Query and Flashback Version Query, grant FLASHBACK andSELECT privileges on specific objects to be accessed during queries or grant theFLASHBACK ANY TABLE privilege to allow queries on all tables.

  • For Flashback Transaction Query, grant the SELECT ANY TRANSACTION privilege.

  • For Execution of undo SQL code, grant SELECT, UPDATE,DELETE, and INSERT privileges for specific tables, as appropriate, to permit execution of undo SQL code retrieved by a Flashback Transaction Query

5为了使用闪回版本查询在10g中,数据库必须运行在10.0兼容性上,必须用下面的命令设置补充日志

alter database add supplemental log data;

6为了在包含lob列的表上使用flashback,使用带retention选项的alter table命令,因为lob列的undo会非常大,你必须指定哪个lob列使用flashback功能。

使用flashback 查询(select .. as of)

使用闪回查询的情况包括:

1恢复丢失的数据或是重做不正确的,提交的改变。例如,如果你错误的删除或是更新了数据,然后提交了,你可以马上改正错误。

2比较现在与过去的数据。

3检查特定时间的事务数据的状态,例如,确定某一天的账号的平衡

4简化应用设计

5提供错误修正的自我服务,让用户修正自己的错误。

例子,假如dba发现12:30分用户chung的记录被删掉了,dba知道在9:30分,数据还在数据库中,dba可以使用闪回查询来检查9:30分的内容来找到数据,dba还可以重新插入丢失的数据

SELECT * FROM employees AS OF TIMESTAMP 
   TO_TIMESTAMP('2004-04-04 09:30:00', 'YYYY-MM-DD HH:MI:SS')
   WHERE last_name = 'Chung';


INSERT INTO employees 
    (SELECT * FROM employees AS OF TIMESTAMP 
     TO_TIMESTAMP('2004-04-04 09:30:00', 'YYYY-MM-DD HH:MI:SS')
     WHERE last_name = 'Chung');

使用闪回查询的提示

1可以指定as of语句,也可以不指定。在ddl或dml中使用as of语句与查询要在一个会话中。

2当在选择是使用timestamp还是scn的时候,记住,orcale内部使用scn映射到3秒内的时间戳中,如果3秒错误不能接受,你就要使用scn而不是timestamp

3可以使用as of来创建视图,如果你使用了相对的时间,那么每次查询的时候都会重新计算

INSERT INTO employees 
    (SELECT * FROM employees AS OF TIMESTAMP 
     TO_TIMESTAMP('2004-04-04 09:30:00', 'YYYY-MM-DD HH:MI:SS')
     WHERE last_name = 'Chung');

4可以再自连接,intersect和minus中使用as of.

使用ora_rowscn

ora_rowscn是一个伪列,代表了一个给定行最近改变的scn,也就是最后一次的commit操作。

SELECT ora_rowscn, last_name, salary 
FROM employees 
WHERE employee_id = 7788;

ORA_ROWSCN    NAME    SALARY
----------    ----    ------
    202553    Fudd      3000

最近的commit操作大约发生在scn202553,可以使用scn_to_timestamp来转换scn到相应的timestamp上。ora_scn实际上市最近一次提交的保守上限值,ora_scn在row_dependent表上更精确。

ora_rowscn的使用在应用程序的开发中,包括并发的控制盒客户缓存的有效上。怎么在并发控制上使用它,考虑下面的场景

你的应用检查一行数据,记录相应的ora_rowscn是202553,稍后,应用程序在记录的记录准确是更新行,这个特定的更新依赖行还没有改变,那么这个操作的ora_rowscn应该仍然是202553,下面是等价的命令

UPDATE employees 
  SET salary = salary + 100 
  WHERE employee_id = 7788 
  AND ora_rowscn = 202553;

这个跟新失败了,因为ora_rowscn不在是202553,这意味着用户或应用程序修改了这行,并且提交了。

ora_scn除了在update的where中使用,你还可以再delete的where中或as of中使用。

闪回版本查询

使用闪回版本查询可以获取特定行的不同的版本,当commit执行的时候,行的新的版本就产生了。 使用select ...version between来使用闪回版本查询。

version {between {scn| timestamp} start and end}

闪回版本查询的伪列

Table 10-1 Flashback Version Query Row Data Pseudocolumns

Pseudocolumn Name Description
VERSIONS_STARTSCN

VERSIONS_STARTTIME

Starting System Change Number (SCN) orTIMESTAMP when the row version was created. This identifies the time when the data first took on the values reflected in the row version. You can use this to identify the past target time for a Flashback Table or Flashback Query operation.

If this is NULL, then the row version was created before the lower time bound of the queryBETWEEN clause.

VERSIONS_ENDSCN

VERSIONS_ENDTIME

SCN or TIMESTAMP when the row version expired. This identifies the row expiration time.

If this is NULL, then either the row version was still current at the time of the query or the row corresponds to aDELETE operation.

VERSIONS_XID Identifier of the transaction that created the row version.
VERSIONS_OPERATION Operation performed by the transaction:I for insertion, D for deletion, or U for update. The version is that of the row that was inserted, deleted, or updated; that is, the rowafter an INSERT operation, the row before a DELETE operation, or the row affected by an UPDATE operation.

Note: For user updates of an index key, a Flashback Version Query may treat anUPDATE operation as two operations, DELETE plus INSERT, represented as two version rows with aD followed by an I VERSIONS_OPERATION.


给定行的版本在version_start开始时有效的知道version_end但是不包含version_end,比如下面的salary在2002,9,9日(包含),到2003,11,25(不包含)是有效的

VERSIONS_START_TIME     VERSIONS_END_TIME     SALARY
-------------------     -----------------     ------
09-SEP-2003             25-NOV-2003           10243

下面是一个典型的版本查询

SELECT versions_startscn, versions_starttime, 
       versions_endscn, versions_endtime,
       versions_xid, versions_operation,
       name, salary  
  FROM employees 
  VERSIONS BETWEEN TIMESTAMP 
      TO_TIMESTAMP('2003-07-18 14:00:00', 'YYYY-MM-DD HH24:MI:SS')
  AND TO_TIMESTAMP('2003-07-18 17:00:00', 'YYYY-MM-DD HH24:MI:SS')
  WHERE name = 'JOE';

伪列versions_xid提供了事务唯一标识符。可以使用这个结合闪回版本查询来定位flashback_transaction_query视图中元数据。

闪回事务查询

闪回事务查询flashback_transaction_query视图,下面的是一个例子

SELECT xid, operation, start_scn,commit_scn, logon_user, undo_sql
     FROM flashback_transaction_query
     WHERE xid = HEXTORAW('000200030000002D');

SELECT xid, logon_user FROM flashback_transaction_query
     WHERE xid IN (SELECT versions_xid FROM employees VERSIONS BETWEEN TIMESTAMP 
      TO_TIMESTAMP('2003-07-18 14:00:00', 'YYYY-MM-DD HH24:MI:SS') AND
      TO_TIMESTAMP('2003-07-18 17:00:00', 'YYYY-MM-DD HH24:MI:SS'));

This example demonstrates the use of a Flashback Transaction Query in conjunction with a Flashback Version Query. The example assumes simple variations of theemployees and departments tables in the sample hr schema.

In this example, a DBA carries out the following series of actions in SQL*Plus:

connect hr/hr
CREATE TABLE emp 
   (empno   NUMBER PRIMARY KEY, 
    empname VARCHAR2(16), 
    salary  NUMBER);
INSERT INTO emp VALUES (111, 'Mike', 555);
COMMIT;

CREATE TABLE dept 
   (deptno   NUMBER, 
    deptname VARCHAR2(32));
INSERT INTO dept VALUES (10, 'Accounting');
COMMIT;

At this point, emp and dept have one row each. In terms of row versions, each table has one version of one row. Next, suppose that an erroneous transaction deletes employee id111 from table emp:

UPDATE emp SET salary = salary + 100 WHERE empno = 111;
INSERT INTO dept VALUES (20, 'Finance'); 
DELETE FROM emp WHERE empno = 111;
COMMIT;

Subsequently, a new transaction reinserts employee id 111 with a new employee name into theemp table.

INSERT INTO emp VALUES (111, 'Tom', 777);
UPDATE emp SET salary = salary + 100 WHERE empno = 111;
UPDATE emp SET salary = salary + 50 WHERE empno = 111;
COMMIT;

At this point, the DBA detects the application error and needs to diagnose the problem. The DBA issues the following query to retrieve versions of the rows in theemp table that correspond to empno 111. The query uses Flashback Version Query pseudocolumns.

connect dba_name/password
SELECT versions_xid XID, versions_startscn START_SCN,
  versions_endscn END_SCN, versions_operation OPERATION,
  empname, salary FROM hr.emp
  VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE
  where empno = 111;

XID              START_SCN  END_SCN   OPERATION  EMPNAME    SALARY
---------------- ---------- --------- ---------- ---------- ----------
0004000700000058 113855               I          Tom        927
000200030000002D 113564               D          Mike       555
000200030000002E 112670     113564    I          Mike       555
3 rows selected

The results table reads chronologically, from bottom to top. The third row corresponds to the version of the row inemp that was originally inserted in the table when the table was created. The second row corresponds to the row inemp that was deleted by the erroneous transaction. The first row corresponds to the version of the row inemp that was reinserted with a new employee name.

The DBA identifies transaction 000200030000002D as the erroneous transaction and issues the following Flashback Transaction Query to audit all changes made by this transaction:

SELECT  xid, start_scn START, commit_scn COMMIT, 
        operation OP, logon_user USER, 
        undo_sql FROM flashback_transaction_query
        WHERE xid = HEXTORAW('000200030000002D');

XID               START   COMMIT  OP       USER   UNDO_SQL
----------------  -----   ------  --       ----   ---------------------------
000200030000002D  195243  195244  DELETE   HR     insert into "HR"."EMP" 
("EMPNO","EMPNAME","SALARY") values ('111','Mike','655');

000200030000002D  195243  195244  INSERT   HR     delete from "HR"."DEPT" 
where ROWID = 'AAAKD4AABAAAJ3BAAB';

000200030000002D  195243  195244  UPDATE   HR     update "HR"."EMP" 
set "SALARY" = '555' where ROWID = 'AAAKD2AABAAAJ29AAA';

000200030000002D  195243  113565  BEGIN  HR

4 rows selected

The rightmost column (undo_sql) contains the SQL code that will undo the corresponding change operation. The DBA can execute this code to undo the changes made by that transaction. TheUSER column (logon_user) shows the user responsible for the transaction.

A DBA might also be interested in knowing all changes made in a certain time window. In our scenario, the DBA performs the following query to view the details of all transactions that executed since the erroneous transaction identified earlier (including the erroneous transaction itself):

SELECT xid, start_scn, commit_scn, operation, table_name, table_owner
  FROM flashback_transaction_query
  WHERE table_owner = 'HR' AND
        start_timestamp >=
          TO_TIMESTAMP ('2002-04-16 11:00:00','YYYY-MM-DD HH:MI:SS');

XID               START_SCN  COMMIT_SCN  OPERATION  TABLE_NAME  TABLE_OWNER
----------------  ---------  ----------  ---------  ----------  -----------
0004000700000058  195245     195246      UPDATE     EMP         HR
0004000700000058  195245     195246      UPDATE     EMP         HR
0004000700000058  195245     195246      INSERT     EMP         HR
000200030000002D  195243     195244      DELETE     EMP         HR
000200030000002D  195243     195244      INSERT     DEPT        HR
000200030000002D  195243     195244      UPDATE     EMP         HR

6 rows selected

在闪回事务查询中,xid的列是raw(8),为了利用建立在xid列上的索引,使用hextoraw转换函数。

可以使用dbms_flashback.get_system_change_number来获得scn

使用scn获取数据更精确,如果使用timestamp,实际获取的值也许比你指定的时间早3s,例如scn1000,1005对应的时间是8:41与8:46,一个在8:41:00到8:45:59的查询被映射到scn1000,8:46的查询被映射到1005

闪回表

闪回表能恢复一个表到之前的状态,这是一个在表被偶然的修改或删除后的一个快速,在线的解决方案。

闪回表可以概括成下面的这些功能:

1恢复表中的数据到timestamp或scn指定的时间

2在线恢复

3自动维护表的所有属性,像是索引,触发器,约束。

4即使在闪回操作后,在原表中的数不会丢失。

5通过约束维护数据的一致性,表的约束不会失效。

6在一个分布式的环境中维护远程的状态。如果一个被复制的表被闪回,那么所有表的修改都被复制要求。

在删除表后,会有下面的一些结果:

1在数据字典中删除了表的定义,表中所有的行都不在可访问。

2表上的所有索引和触发器都被删除。

3pl/sql仍然存在,但是变成无效状态。

4同义词存在,但是被使用的时候会报错。

5表的所有段返回表空间的空闲空间中,可以被别的对象继续使用。

在删除表的时候,数据库通常会重命名表,然后把他反倒recycle bin中,然后可以使用flashback table来闪回。如果想要马上就释放空间,应该使用下面的语句:

drop table hr.admin_emp purge;

使用flashback drop与管理recycle bin

什么是recycle bin

recycle bin实际上市一个数据字典表,包含了删除对象的信息,被删除的表包含索引,约束,嵌套表这些没有删除实际上占用空间的对象。

每一个用户可以想象成有他们自己的recycle bin,每个用户访问的recycle bin中的对象都是他们自己的。可以通过下面的遇见来查看

select * from recyclebin;

recycle bin中对象的命名

是系统命名的,命名的方式是:

BIN$unique_id$version

unique_id是一个26个字符的标示符,version是一个被数据库分配的数字。

启用与禁用recycle bin

To disable the recycle bin:

  • Issue one of the following statements:

    ALTER SESSION SET recyclebin = OFF;
    
    ALTER SYSTEM SET recyclebin = OFF;
    
    

To enable the recycle bin:

  • Issue one of the following statements:

    ALTER SESSION SET recyclebin = ON;
    
    ALTER SYSTEM SET recyclebin = ON;
    

查看recycle bin中的对象

View Description
USER_RECYCLEBIN This view can be used by users to see their own dropped objects in the recycle bin. It has a synonymRECYCLEBIN, for ease of use.
DBA_RECYCLEBIN This view gives administrators visibility to all dropped objects in the recycle bin

查看被删除对象的原来的名字

select object_name,original_name from dba_recyclebin where owner='HR';

可以通过show recycelbin来查看回收站中的内容

你可以查看回收站中对象的内容,但是你要指定对象的标示符:

SELECT * FROM "BIN$yrMKlZaVMhfgNAgAIMenRA==$0";

purging recycle bin中的对象

PURGE TABLE BIN$jsleilx392mk2=293$0;

通过指定的对象名称purge

PURGE TABLE int_admin_emp;

可以通过表空间名来purge表空间对象或是指定表空间中一个用户对象。

PURGE TABLESPACE example;
PURGE TABLESPACE example USER oe;

使用下面的语句删除owner的对象。

PURGE RECYCLEBIN;

在recycle bin中恢复表

使用flashback table .. to before drop来恢复在recycle bin中的表。你可以指定在recycle bin中的名字也可以指定表原来的名字,可以使用rename to来重命名,下面是个例子

flashback table int_admin_emp to before drop rename to int2_admin_emp;

在你删除表多次后,使用系统生成的名字就很有用,比如你删除了init2_admin_em很多次,想要闪回第二个版本的表,使用下面的方法:

SELECT object_name, original_name FROM recyclebin;    

OBJECT_NAME                    ORIGINAL_NAME
------------------------------ --------------------------------
BIN$yrMKlZaLMhfgNAgAIMenRA==$0 INT2_ADMIN_EMP
BIN$yrMKlZaVMhfgNAgAIMenRA==$0 INT2_ADMIN_EMP
BIN$yrMKlZaQMhfgNAgAIMenRA==$0 INT2_ADMIN_EMP

FLASHBACK TABLE BIN$yrMKlZaVMhfgNAgAIMenRA==$0 TO BEFORE DROP 
   RENAME TO int2_admin_emp;


闪回事务查询: