首页 > 技术文章 > Oracle中flashback的使用

dayu-liu 2019-06-18 17:19 原文

1、闪回技术都包含哪些技术

  • flashback query
  • flashback data archive
  • flashback transaction query
  • flashback transaction
  • flashback table
  • flashback drop
  • flashback database

2、flashback query【主要是利用undo查询一段时间以前的数据】

  • 闪回时间点查询
select * from test as of timestamp to_timestamp('','') where object_id=100;

 

  • 闪回版本查询

3、flashback data archive【将原本只能保存在undo中的撤销数据保存在普通表空间中,这样可以查询表很长时间以前的旧数据】

  •  如何对表创建flashback data archive。
SQL> create flashback archive default fda_default tablespace fda retention 1 year;          

Flashback archive created.


SQL> grant flashback archive on fda_default to dayu;

Grant succeeded.

SQL> alter table dayu.fda_test flashback archive;

Table altered.

SQL> select count(*) from dayu.fda_test as of timestamp (systimestamp -interval '7' month);
select count(*) from dayu.fda_test as of timestamp (systimestamp -interval '7' month)
                          *
ERROR at line 1:
ORA-08180: no snapshot found based on specified time


SQL> select count(*) from dayu.fda_test as of timestamp (systimestamp -interval '1' day);
select count(*) from dayu.fda_test as of timestamp (systimestamp -interval '1' day)
                          *
ERROR at line 1:
ORA-01466: unable to read data - table definition has changed



 

  • 在fda中,创建的flashback data archive是如何存储的?
SEGMENT_NAME                                      SEGMENT_TYPE
--------------------------------------------------------------------------------- ------------------
FDA_TEST                                      TABLE
SYS_FBA_DDL_COLMAP_73240                              TABLE
SYS_FBA_TCRV_73240                                  TABLE
SYS_FBA_HIST_73240                                  TABLE PARTITION                               --这个表存放的就是fda_test的历史数据
SYS_FBA_TCRV_IDX_73240 INDEX

 

  • 开起来flashback data archive的表如果有不被允许的ddl会怎么样?
SQL> alter table dayu.fda_test shrink space;
alter table dayu.fda_test shrink space
*
ERROR at line 1:
ORA-55610: Invalid DDL statement on history-tracked table
  • 哪些ddl可以在开启历史表的的表上操作?
1、对字段的add、drop、rename、modify修改
2、对约束的add、drop、rename修改
3、对分区的drop、truncate操作
4、对表的truncate和rename操作

 

4、flashback transaction query【需要开启最小补充日志;查询返回的结果是将当前数据修改为以前数据的撤销sql】

 

5、flashback transaction【撤销已经执行的事务】

  •  查询过去一段时间表上的事务

select
distinct xid,commit_scn from flashback_transaction_query where table_name='TEST' and table_owner='DAYU' and commit_timestamp > systimestamp - interval '10' minute order by commit_scn; --没有结果呢怎么?

 以下为测试过程:

SQL> alter database add supplemental log data;  --这个比较关键

Database altered.

SQL> select SUPPLEMENTAL_LOG_DATA_MIN from v$database;

SUPPLEMENTAL_LOG_DATA_MI
------------------------
YES

SQL> create user test identified by test;

User created.

SQL> grant connect, resource to test;

Grant succeeded.

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

Table created.

SQL>  select * from test.emp;

no rows selected

SQL> desc test.emp;
 Name                       Null?    Type
 ----------------------------------------- -------- ----------------------------
 EMPNO                            NUMBER(4)
 ENAME                            VARCHAR2(10)
 JOB                            VARCHAR2(9)
 MGR                            NUMBER(4)
 HIREDATE                        DATE
 SAL                            NUMBER(7,2)
 COMM                            NUMBER(7,2)
 DEPTNO                         NUMBER(2)

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

1 row created.

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

1 row created.

SQL> commit;

Commit complete.

SQL> select * from test.emp;

     EMPNO ENAME              JOB                     MGR
---------- ------------------------------ --------------------------- ----------
HIREDATE          SAL        COMM     DEPTNO
------------------ ---------- ---------- ----------
    10 AAA                  STF
13-APR-92         1000         100     10

    20 BBB                  STF                      10
13-APR-92          500         100     10


SQL> select dbms_flashback.get_system_change_number from dual;

GET_SYSTEM_CHANGE_NUMBER
------------------------
         1138207

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

1 row created.

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

1 row created.

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

1 row created.

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

1 row created.

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
------------------------
         1138277

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

Table created.

SQL> CREATE OR REPLACE PROCEDURE extract_txn_ids (lcrscn IN NUMBER, escn in number) AS
lname VARCHAR2(256);
vsql varchar2(2000);
BEGIN
    dbms_logmnr.start_logmnr(startscn => lcrscn,
                              endscn => escn,
                              OPTIONS => DBMS_LOGMNR.DICT_FROM_ONLINE_CATALOG+DBMS_LOGMNR.CONTINUOUS_MINE);
    insert into changed_tables
          select distinct seg_name,xid,scn
            from v$logmnr_contents where seg_owner = 'TEST'
                  and scn >= lcrscn
                  and scn<= escn;
    commit;
END;
/  2    3    4    5    6    7    8    9   10   11   12   13   14   15  

Procedure created.

SQL> exec extract_txn_ids(1138207,1138277);

PL/SQL procedure successfully completed.

SQL> select * from changed_tables;
SQL> col TABLE_NAME for a40
SQL> /

TABLE_NAME                 XID             SCN
---------------------------------------- ---------------- ----------
EMP                     04001E0004030000    1138211
EMP                     07001F00EB020000    1138273
EMP                     04001E0004030000    1138214
EMP                     04001E0004030000    1138210
EMP                     050003006A040000    1138264
EMP                     04001E0004030000    1138216

6 rows selected.

SQL> create or replace procedure txn_backout(sscn in number)
 as
   txn_array sys.xid_array := sys.xid_array();
   i number;
begin
       i := 1;
       --initialize xid_array from changed_tables
       for txn in (select distinct xid from changed_tables)
       loop
         txn_array.extend;
         txn_array(i) := txn.xid;
         i := i + 1;
       end loop;
       i := i - 1;
       -- 3 input variables are passed to transaction_backout
       -- i number of txns
       -- txn_array array of txn ids
       -- sscn starting point to logminer
       dbms_flashback.transaction_backout (
             numtxns => i,
             xids => txn_array,
             options => dbms_flashback.cascade,
             scnhint => sscn
           );
       --issue commit as dbms_flashback.transaction_backout does not include commit and ----txn backout.
         commit;
END;
/  2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   27   28  

Procedure created.

SQL> exec txn_backout(sscn =>1138207);
BEGIN txn_backout(sscn =>1138207); END;

*
ERROR at line 1:
ORA-55510: Mining could not start
ORA-06512: at "SYS.DBMS_FLASHBACK", line 37
ORA-06512: at "SYS.DBMS_FLASHBACK", line 70
ORA-06512: at "SYS.TXN_BACKOUT", line 19
ORA-06512: at line 1


SQL>  exec dbms_logmnr.end_logmnr;  --这里测试过程中并没有开启logmnr,哪里打开的?

PL/SQL procedure successfully completed.

SQL> exec txn_backout(sscn =>1138207);

PL/SQL procedure successfully completed.

 

6、flashback table【利用undo将表恢复到以前的状态】

  1.  模拟测试
SQL> update scn_test set object_name='DY' where rownum < 20000;

19999 rows updated.

SQL> commit;

Commit complete.

SQL> flashback table scn_test to timestamp (systimestamp -interval '10' miniute);
flashback table scn_test to timestamp (systimestamp -interval '10' miniute)
                                                                   *
ERROR at line 1:
ORA-30089: missing or invalid <datetime field>


SQL> flashback table scn_test to timestamp (systimestamp -interval '10' minute);
flashback table scn_test to timestamp (systimestamp -interval '10' minute)
                *
ERROR at line 1:
ORA-08189: cannot flashback the table because row movement is not enabled


SQL> alter table scn_test enable row movement;

Table altered.

SQL> flashback table scn_test to timestamp (systimestamp -interval '10' minute);

Flashback complete.

SQL> select object_name from scn_test where rownum< 10;

OBJECT_NAME
------------------------------
V$RSRC_CONS_GROUP_HISTORY
V_$RSRC_PLAN_HISTORY
V$RSRC_PLAN_HISTORY
V_$BLOCKING_QUIESCE
V$BLOCKING_QUIESCE
V_$PX_BUFFER_ADVICE
V_$FLASHBACK_DATABASE_LOG
V$FLASHBACK_DATABASE_LOG
V_$FLASHBACK_DATABASE_STAT

9 rows selected.
  • 开启flashback table的几个条件
  1. 对表开启row movement
  2. undo要设置的合适
  3. 另外sys用户的表是无法做flashback的。

 

7、flashback drop【从回收站中将表恢复】

 

8、flashback database【测试时必须要开启闪回日志】

SQL> archive log list;
Database log mode           Archive Mode
Automatic archival           Enabled
Archive destination           USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence     47
Next log sequence to archive   49
Current log sequence           49
SQL> 
SQL> 
SQL> show parameter db_recovery_file_dest_size

NAME                     TYPE     VALUE
------------------------------------ ----------- ------------------------------
db_recovery_file_dest_size         big integer 4977M
SQL> 
SQL>  alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';

Session altered.

SQL>  select oldest_flashback_scn,oldest_flashback_time from v$flashback_database_log;

OLDEST_FLASHBACK_SCN OLDEST_FLASHBACK_TI
-------------------- -------------------
          730972 2019-08-26 17:08:16



SQL> create table flash1 as select * from dba_objects;

Table created.

SQL> create table flash2 as select * from flash1;

Table created.

SQL> create table flash3 as select * from flash1;

Table created.

SQL>  select sysdate from dual;

SYSDATE
-------------------
2019-08-26 17:10:48

SQL>  truncate table flash2;

Table truncated.

SQL> drop table flash3;

Table dropped.

SQL> shutdown immediate
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup mount exclusive;
ORACLE instance started.

Total System Global Area  592957440 bytes
Fixed Size            2215544 bytes
Variable Size          230687112 bytes
Database Buffers      356515840 bytes
Redo Buffers            3538944 bytes
Database mounted.
SQL> flashback database to timestamp(to_date('2019-08-26 17:10:48','yyyy-mm-dd hh24:mi:ss'));

Flashback complete.


SQL> alter database open resetlogs;

Database altered.

在此过程中,主要使用了flashback log


-rw-r----- 1 oracle oinstall 8200192 8月 26 17:22 o1_mf_gp78d05s_.flb
[ocm1:oracle]:/oracle/app/oracle/flash_recovery_area/OCM1/flashback>pwd
/oracle/app/oracle/flash_recovery_area/OCM1/flashback
[ocm1:oracle]:/oracle/app/oracle/flash_recovery_area/OCM1/flashback>ls
o1_mf_gp78d05s_.flb
[ocm1:oracle]:/oracle/app/oracle/flash_recovery_area/OCM1/flashback>

 

 

推荐阅读