首页  >  文章  >  数据库  >  使用Flashback Transaction方法来恢复数据表数据

使用Flashback Transaction方法来恢复数据表数据

WBOY
WBOY原创
2016-06-07 15:10:321002浏览

进行精细粒度的数据误操作还原,是我们在实际工作中经常遇到的场景。Oracle基于Redo Log和Undo机制,提供实现了诸多分支技术,如

进行精细粒度的数据误操作还原,是我们在实际工作中经常遇到的场景。Oracle基于Redo Log和Undo机制,提供实现了诸多分支技术,如Flashback、Log Miner等来进行多粒度的数据恢复。在Oracle 11g中,dbms_flashback.transaction_backout方法提供了在数据库online状态下,直接逆回数据库事务和相关依赖事务的能力。

本篇主要介绍如何使用logminer和Flashback包新方法,来实现Oracle事务的逆回操作。

1、环境介绍

笔者使用Oracle 11g进行测试,版本为11.2.0.4。

SQL> select * from v$version;

BANNER

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

Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

PL/SQL Release 11.2.0.4.0 - Production

CORE    11.2.0.4.0 Production

TNS for Linux: Version 11.2.0.4.0 - Production

NLSRTL Version 11.2.0.4.0 – Production

由于需要使用Logminer组件,,所以数据库层面需要切换到归档模式,同时启动最小数据级别的补充日志(Supplemental Log)。

SQL> shutdown immediate;

Database closed.

Database dismounted.

ORACLE instance shut down.

SQL> startup mount;

ORACLE instance started.

Total System Global Area 1603411968 bytes

Fixed Size                  2253664 bytes

Variable Size            973081760 bytes

Database Buffers          620756992 bytes

Redo Buffers                7319552 bytes

Database mounted.

SQL> alter database archivelog;

Database altered.

SQL> alter database add supplemental log data;

Database altered.

启动数据库进入read write状态。

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    38

Next log sequence to archive  40

Current log sequence          40

SQL> select SUPPLEMENTAL_LOG_DATA_MIN from v$database;

SUPPLEMENTAL_LOG_DATA_MIN

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

YES

2、实验数据构建

为了有一个干净的数据环境,全新创建一个用户Test,进行测试。

SQL> create user test identified by test;

User created

SQL> grant connect, resource to test;

Grant succeeded

构建数据表emp,插入部分数据作为初始状态。

SQL> create table test.emp as select * from scott.emp where 1=0;

Table created

SQL> select * from test.emp;

EMPNO ENAME      JOB        MGR HIREDATE          SAL      COMM DEPTNO

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

SQL> desc test.emp;

Name    Type        Nullable Default Comments 

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

EMPNO    NUMBER(4)    Y                         

ENAME    VARCHAR2(10) Y                         

JOB      VARCHAR2(9)  Y                         

MGR      NUMBER(4)    Y                         

HIREDATE DATE        Y                         

SAL      NUMBER(7,2)  Y                         

COMM    NUMBER(7,2)  Y                         

DEPTNO  NUMBER(2)    Y                         

SQL> insert into test.emp values (10,'AAA','STF', null,sysdate-10000,1000,100,'10');

1 row inserted

SQL> insert into test.emp values (20,'BBB','STF', 10,sysdate-10000,500,100,'10');

1 row inserted

SQL> commit;

Commit complete

SQL> select * from test.emp;

EMPNO ENAME      JOB        MGR HIREDATE          SAL      COMM DEPTNO

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

  10 AAA        STF            1988/2/5 13  1000.00    100.00    10

  20 BBB        STF          10 1988/2/5 13    500.00    100.00    10

此时,SCN时间点如下,作为工作的起始时间点:

SQL> select dbms_flashback.get_system_change_number from dual;

GET_SYSTEM_CHANGE_NUMBER

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

                1795785

之后进行了一系列的DML操作。

SQL> insert into test.emp values (30,'CCC','STF', 10,sysdate-10000,500,100,'10');

1 row inserted

SQL> insert into test.emp values (40,'DDD','MANG', null,sysdate-10000,5000,1000,'10');

1 row inserted

SQL> insert into test.emp values (50,'EEE','STF', 10,sysdate-10000,500,100,'10');

1 row inserted

SQL> insert into test.emp values (60,'FFF','STF', null,sysdate-20000,5000,100,'10');

1 row inserted

SQL> commit;

Commit complete

SQL> update test.emp set comm=1000 where empno=50;

1 row updated

SQL> commit;

Commit complete

SQL> update test.emp set comm=1000 where empno=60;

1 row updated

SQL> commit;

Commit complete

操作之后,数据库时间点如下:

SQL> select dbms_flashback.get_system_change_number from dual;

GET_SYSTEM_CHANGE_NUMBER

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

                1795891

数据肯定发生了变化,现在实验目标是将数据恢复回去,恢复到SCN=1795785时间点Emp数据表的状态。

3、数据恢复实验

首先,需要创建一个数据表changed_tables,记录下从Log Miner中抽取出的与数据表EMP相关的事务信息。

SQL> create table changed_tables (table_name varchar2(256), xid raw(8), scn number);

Table created

SQL> desc changed_tables;

Name      Type          Nullable Default Comments 

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

TABLE_NAME VARCHAR2(256) Y                         

XID        RAW(8)        Y                         

SCN        NUMBER        Y                         

创建一个Stored Procedure,用于从Log Miner视图中将相关事务操作保存在changed_tables中。

SQL> CREATE OR REPLACE PROCEDURE extract_txn_ids (lcrscn IN NUMBER, escn in number) AS

  2  lname VARCHAR2(256);

  3  vsql varchar2(2000);

  4  BEGIN

  5      dbms_logmnr.start_logmnr(startscn => lcrscn,

  6                                endscn => escn,

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn