本篇主要介绍如何使用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 com