Home  >  Article  >  Database  >  使用Flashback Transaction方法来恢复数据表数据

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

WBOY
WBOYOriginal
2016-06-07 15:10:321003browse

进行精细粒度的数据误操作还原,是我们在实际工作中经常遇到的场景。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,

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn