Flashback Query, Flashback Version Query

[Oracle 9i & 10g] Flashback Query, Flashback Version Query, Flashback Table, etc

Oracle 9i 引入了flashback query,可以方便我們查詢過去一個時間“點”的數據庫的狀態。比如我們在T1時刻更改了一條記錄,接着在T2時刻刪除了該條數據(並且commit了),我們可以通過flashback query來查詢到T1時刻的該條記錄。

Oracle 10g把flashback query推進了一步,不光可以查詢過去一個時間“點”的數據庫狀態, 而且可以查詢過去一段時間內數據狀態變化的過程(不同版本), 所以叫做flashback version query。

不管是flashback query還是flashback version query, 所有的這些“歷史數據”都保存在了Undo Segment上。 (在Orace 9i之前叫做rollback segment, 對應於手動來管理這部分空間)因此,我們可以查詢到的歷史數據受限於undo segment的大小(不太準確),因爲undo segment在空間不夠的時候會被覆寫。當然,可以設置參數UNDO_RETENTION來設置數據在Undo Segment上的“存活”時間(單位是秒)。

那麼flashback query有啥好處呢? 這是個很容易想到的問題。 我覺得一個好處就是方便我們來undo我們之前做的“誤”操作,比如我們不小心刪除了一條數據並且commit了,很顯然用rollback已經不起作用了,這個時候我們可以通過flashback query找到那個時刻的數據,把它重新插入到數據庫中。(或者通過flashback table來直接恢復到之前的數據狀態)

那麼我們如何查詢到過去某個時刻的數據(從undo segment上)呢, Oracle 9i支持兩種方式,一種是SCN(system change number),另外一種是timestamp。 Oracle10g R2 增加了一種方式,叫做restore point, 這個接下來都會介紹到。

提到flashback, 可能會容易想到oracle 10g引入了flash recovery area(FRA)的概念,這個跟flashback query沒有多大關係,FRA主要跟RMAN,數據庫的恢復有關,具體可以參見這裏

同樣,提到flashback, 還會想到oracle 10g R1 引入的flashback table。 從10g開始,用drop語句來刪除一個數據庫對象並不會直接把該數據庫對象從數據庫中徹底刪除掉,而是把該數據庫對象改了個名字放到了recyclebin中, 當然如果想徹底刪除該數據庫對象,可以在drop 的時候加上purge, 比如 drop table XXX purge,這樣改數據庫對象就不會放到recyclebin中,而是直接被刪除了。正是因爲數據庫對象暫時保存在了recyclebin中,我們可以通過flashback語句來把該數據庫對象恢復過來,例如 flashback table XXX to before drop. 對於這部分內容,最後再說,先從flashback query 談起。

1. Flashback Query in Oracle 9i (參考Adrian Billington的Flashback Query in Oracle 9i)

Flashback query 在9.1 和9.2還是有點區別的,9.1的用法比較繁瑣,不方便,9.2改進了許多。

(1) 應用flashback query的先決條件

undo_management = auto (在參數文件pfile/spfile中設置)

undo_retention = n ( n是個正整數,單位是sec, 也是在參數文件pfile/spfile中設置)

undo_tablespace = (也是在參數文件中設置)

FLASHBACK 或者 FLASHBACK ANY的系統權限(system priviledge)

     執行DBMS_FLASHBACK的權限

(2) 示例數據

SQL> create table t
  2  as
  3  select owner, table_name, tablespace_name
  4  from all_tables
  5  where rownum <= 5;

Table created.

SQL> select * from t;

OWNER                TABLE_NAME                     TABLESPACE_NAME
-------------------- ------------------------------ ----------------------
--
SYS                  ICOL$                          SYSTEM
SYS                  CON$                           SYSTEM
SYS                  UNDO$                          SYSTEM
SYS                  PROXY_ROLE_DATA$               SYSTEM
SYS                  FILE$                          SYSTEM

SQL>

【提示】在Oracle9i(9.1 和 9.2)中,Oracle建議我們等待大約5分鐘之後再進行flashback query新創建的表,否則可能會碰到這個錯誤ORA-01466: unable to read data - table definition has changed. 注意這個5分鐘時間間隔正好是9i 中SCN和timestamp相map的時間間隔,雖然可以用timestamp來進行flashback query,但實質還是根據該timestamp對應的SCN來進行flasbback query, 由於timestamp不是實時地跟SCN對應上, 因此我們需要等段時間來讓timestamp跟SCN同步上, 因此用SCN會比timestamp更準確些。注意SCN會在每個commit的時候增長。

(3) 9.1: DBMS_FLASHBACK

在Oracle9i中,需要用到package DBMS_FLASHBACK來enable/disable FLASHBACK query。

在進行操作之前,首先得到當前的SCN以便之後flashback query到這個時刻的數據,

SQL> select dbms_flashback.get_system_change_number as scn from dual;

       SCN
----------
   1517851

SQL>

接下來對剛纔創建的Table t做一些更改(並commit),

SQL> update t set tablespace_name = LOWER(tablespace_name);

5 rows updated.

SQL> commit;

Commit complete.

SQL>

可以看到數據發生了變化

SQL> select * from t;

OWNER                TABLE_NAME                     TABLESPACE_NAME
-------------------- ------------------------------ ------------------------
--
SYS                  ICOL$                          system
SYS                  CON$                           system
SYS                  UNDO$                          system
SYS                  PROXY_ROLE_DATA$               system
SYS                  FILE$                          system

SQL>

現在我們可以使用flashback query來得到我們更改之前的數據。(需要先用DBMS_FLASHBACK.ENABLE_AT_SYSTEM_CHANGE_NUMBER(scn) 來把數據庫設置成flashback 狀態,之後我們就會看到這個SCN時的數據庫狀態)

SQL> exec DBMS_FLASHBACK.ENABLE_AT_SYSTEM_CHANGE_NUMBER(1517851);

PL/SQL procedure successfully completed.

SQL> select * from t;

OWNER                TABLE_NAME                     TABLESPACE_NAME
-------------------- ------------------------------ ------------------
--
SYS                  ICOL$                                      SYSTEM
SYS                  CON$                                       SYSTEM
SYS                  UNDO$                                     SYSTEM
SYS                  PROXY_ROLE_DATA$                SYSTEM
SYS                  FILE$                                        SYSTEM

SQL>

可以看到tablespace_name的數據都變成更改之前的樣子了。

如果想看到數據庫“實際”的狀態,我們需要調用DBMS_FLASHBACK.DIABLE來離開flashback mode.

SQL> exec DBMS_FLASHBACK.DISABLE;

PL/SQL procedure successfully completed.

SQL> select * from t;

OWNER                TABLE_NAME                     TABLESPACE_NAME
-------------------- ------------------------------ -------------------
--
SYS                  ICOL$                          system
SYS                  CON$                           system
SYS                  UNDO$                          system
SYS                  PROXY_ROLE_DATA$               system
SYS                  FILE$                          system

SQL>

(4) 9.2 as of [SCN | timestamp]

Oracle 9.2引入了新的機制來實現flashback query, 而不是9.1中那樣需要手動去調用dbms_flaback中的存儲過程。在Oracle 9.2中,我們可以直接通過SQL語句來實現,只需要加入(AS OF SCN xxx 或者 AS OF TIMESTAMP xxx) 就可以了。

現在來看看剛纔在9.1中的做法,如何在9.2中來實現,(這次更改table_name).

SQL> alter session set NLS_TIMESTAMP_FORMAT = 'DD-MON-YYYY HH24:MI:SS.FF3';

Session altered.

SQL> select localtimestamp from dual;

LOCALTIMESTAMP
---------------------------------------------------------------------------
30-DEC-2009 10:51:11.656

SQL> select * from t;

OWNER                TABLE_NAME                     TABLESPACE_NAME
-------------------- ------------------------------ ---------------------------
--
SYS                  ICOL$                          system
SYS                  CON$                           system
SYS                  UNDO$                          system
SYS                  PROXY_ROLE_DATA$               system
SYS                  FILE$                          system

SQL> update t set table_name = lower(table_name);

5 rows updated.

SQL> commit;

Commit complete.

SQL> select * from t;

OWNER                TABLE_NAME                     TABLESPACE_NAME
-------------------- ------------------------------ ---------------------------
SYS                  icol$                          system
SYS                  con$                           system
SYS                  undo$                          system
SYS                  proxy_role_data$               system
SYS                  file$                          system

現在可以通過AS OF TIMESTAMP 來實現flashback query了。

SQL> select * from t
  2  AS OF TIMESTAMP to_timestamp('30-DEC-2009 10:51:11.656');

OWNER                TABLE_NAME                     TABLESPACE_NAME
-------------------- ------------------------------ ------------------
--
SYS                  ICOL$                          system
SYS                  CON$                           system
SYS                  UNDO$                          system
SYS                  PROXY_ROLE_DATA$               system
SYS                  FILE$                          system

很顯然,這比在oracle 9.1中簡單地多。

2. Flashback Version Query in oracle 10g  (參考Adrian Billington的 flashback version query in oracle 10g)

(1) 先創建需要的示例數據,

SQL> create table fbt
  2  ( x integer,
  3    y timestamp,
  4    z varchar2(30));

Table created.

SQL> exec dbms_lock.sleep(10);

PL/SQL procedure successfully completed.

SQL> insert into fbt values(1, LOCALTIMESTAMP, 'Initial population');

1 row created.

SQL> commit;

Commit complete.

【注意】注意,這裏用dbms_lock sleep了10秒鐘,然後才插入數據(其實沒啥關係,我認爲)。 Oracle建議這麼做,是爲了避免遇到錯誤ORA-01466: unable to read data - table definition has changed。這個錯誤只有當flashback back query針對該剛剛建立的表執行時纔會出現。

(2) 對數據進行一系列的更改,並執行commit

SQL> alter session set NLS_TIMESTAMP_FORMAT = 'DD-MON-YYYY HH24:MI:SS.FF3';

Session altered.

SQL> select LOCALTIMESTAMP as lower_bound from dual;

LOWER_BOUND
---------------------------------------------------------------------------
30-DEC-2009 11:35:03.981

SQL> update fbt set y = LOCALTIMESTAMP, z = 'First update';

1 row updated.

SQL> commit;

Commit complete.

SQL> update fbt set y = LOCALTIMESTAMP, z = 'Second update';

1 row updated.

SQL> commit;

Commit complete.

SQL> select LOCALTIMESTAMP as upper_bound from dual;

UPPER_BOUND
---------------------------------------------------------------------------
30-DEC-2009 11:36:32.999

SQL> delete from fbt where x = 1;

1 row deleted.

SQL> commit;

Commit complete.

SQL> select * from fbt;

no rows selected

(3) Flashback version query

雖然現在表fbt裏面沒有數據,但是可以通過flashback version query來查到之前的“歷史變化”數據。 Flashback version query是通過from語句的擴展語句 versions between. 有兩種形式的versions between

VERSIONS BETWEEN TIMESTAMP [lower bound] AND [upper bound]

VERSIONS BETWEEN SCN [lower bound] AND [upper bound]

lower bound/ upper bound 可以是具體的timestamp/scn, 也可以是關鍵字minvalue/maxvalue. 這些關鍵字讓Oracle去找到所有的versions, 當然這要受制於undo_retention參數設置的大小,畢竟這部分信息是放在undo segment上的。

SQL> select x, y, z
  2  from fbt VERSIONS BETWEEN TIMESTAMP MINVALUE AND MAXVALUE
  3  order by  y;

         X Y                                                      Z
---------- ------------------------------ ------------------------------
         1 30-DEC-2009 11:33:58.667       Initial population
         1 30-DEC-2009 11:35:27.374       First update
         1 30-DEC-2009 11:36:15.373       Second update
         1 30-DEC-2009 11:36:15.373       Second update

從結果可以看出,之前做的操作都去取出來了,但是注意Second update出現了兩條記錄,這個有點奇怪。 還好flashback version query提供了一些pseudo-columns來幫助我們分析,參見下一部分。

(3) Versions pseudo-columns

Oracle 10g提供了一些pseudo-columns來幫助我們分析每個version的數據,

  • VERSIONS_STARTTIME (start timestamp of version);
  • VERSIONS_STARTSCN (start SCN of version);
  • VERSIONS_ENDTIME (end timestamp of version);
  • VERSIONS_ENDSCN (end SCN of version);
  • VERSIONS_XID (transaction ID of version); and
  • VERSIONS_OPERATION (DML operation of version).

我們可以通過查詢這些pseudo columns來獲知每個版本的數據信息,

SQL>

  1  select z,
  2    versionS_starttime,
  3    versionS_endtime,
  4    versionS_xid,
  5    versionS_operation
  6  from fbt VERSIONS BETWEEN TIMESTAMP MINVALUE AND MAXVALUE
  7* order by versions_endtime
SQL> /

Z                              VERSIONS_STARTTIME             VERSIONS_ENDTIME               VERSIONS_XID                   VERSIONS_OPERATION
------------------------------ ------------------------------ ------------------------------ ------------------------------ -------------------
Initial population             30-DEC-2009 11:33:57.000       30-DEC-2009 11:35:39.000       06001B004C030000               I
First update                   30-DEC-2009 11:35:39.000       30-DEC-2009 11:36:18.000       0900100063030000               U
Second update                  30-DEC-2009 11:36:18.000       30-DEC-2009 11:36:54.000       0100250048030000              U
Second update
                  30-DEC-2009 11:36:54.000                                      0900070063030000              D

從這裏可以看到,兩條Second update 其實是對應兩個操作,一個是update (U), 還有一個是Delete (D)。

從這個記錄同時可以看出刪除操作是最後一步,因爲對應的VERSIONS_ENDTIME是NULL。

(4) Flashback transaction query

Oracle 還提供了一個新的視圖, FLASHBACK_TRANSACTION_QUERY 來提供更多的關於data version的信息。查詢這個視圖需要SELECT ANY TRANSACTION 的系統權限。

SQL> desc flashback_transaction_query
 Name                          Null?    Type
 ----------------------------- -------- --------------------
 XID                                    RAW(8)
 START_SCN                              NUMBER
 START_TIMESTAMP                        DATE
 COMMIT_SCN                             NUMBER
 COMMIT_TIMESTAMP                       DATE
 LOGON_USER                             VARCHAR2(30)
 UNDO_CHANGE#                           NUMBER
 OPERATION                              VARCHAR2(32)
 TABLE_NAME                             VARCHAR2(256)
 TABLE_OWNER                            VARCHAR2(32)
 ROW_ID                                 VARCHAR2(19)
 UNDO_SQL                               VARCHAR2(4000)

(5) Timestamp 和 SCN 之間的轉換

Oracle 10g提供了兩個函數TIMESTAMP_TO_SCN和SCN_TO_TIMESTAMP來進行timestamp 和 scn之間的轉換。 SCN 可以通過dbms_flashback.get_system_change_number來得到, timestamp可以通過localtimestamp和systimestamp來獲得。

SQL> alter session set NLS_TIMESTAMP_FORMAT='DD-MON-YYYY HH24:MI:SS.FF3';

Session altered.

SQL> select SYSTIMESTAMP, LOCALTIMESTAMP,
  2     DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER as scn
  3  from dual;

SYSTIMESTAMP                                                                LOCALTIMESTAMP
                                                       SCN
--------------------------------------------------------------------------- ------------------------
--------------------------------------------------- ----------
30-DEC-09 03.18.41.955000 PM +08:00                                         30-DEC-2009 15:18:41.955
                                                           1537555

SQL> select SCN_TO_TIMESTAMP(1537555) as ts from dual;

TS
---------------------------------------------------------------------------
30-DEC-2009 15:18:39.000

SQL> select TIMESTAMP_TO_SCN('30-DEC-2009 15:18:39.000') from dual;

TIMESTAMP_TO_SCN('30-DEC-200915:18:39.000')
-------------------------------------------
1537555

3. Flashback table in 10g (參考Adrian Billington的 flashback table in 10g)

Oracle 10g 引入了flashback table 和 flashback database, 這裏只cover flashback table部分。

Flashback table 跟 Flashback query的區別在於, flashback table會把表中的數據永久地恢復到之前的狀態,而flashback query並沒有對錶中的數據進行恢復,而只是返回之前時刻的數據。

(1) 準備工作

SQL> drop table t purge;

Table dropped.

SQL> create table t
  2  nologging
  3  enable row movement
  4  as
  5    select object_type as x
  6    from all_objects;

Table created.

爲了可以把一個表flashback to 之前的一個狀態,需要滿足兩個條件

> 該表必須是enable row movement的, 因爲flashback 一個表的時候,表中每條記錄的rowid會發生變化。這可以通過alter table或在創建表的時候指定,如上例。

> 執行操作的user要有FLASHBACK ANY TABLE的系統權限,或者目標表被賦予了改權限。

創建好表之後,最好等幾分鐘讓SCN增加。如果嘗試去flashback一個新創建的表,可能會遇到ORA-01466: unable to read data - table definition has changed

(2) Flashback to a previous state

Flashback table主要是一個數據庫恢復的方法,一般用來恢復被誤刪除的表中數據或整個表。

首先刪除表t中記錄爲PACKAGE的數據,並commit,

SQL> delete from t where x = 'PACKAGE';

1204 rows deleted.

SQL> commit;

Commit complete.

SQL> select count(*) from t where x = 'PACKAGE';

  COUNT(*)
----------
         0

現在可以通過flashback table來讓表t回到之前的狀態, (兩分鐘之前)

SQL> flashback table t to TIMESTAMP systimestamp - interval '2' minute;

Flashback complete.

SQL> select count(*) from t where x = 'PACKAGE';

  COUNT(*)
----------
      1204

我們也可以用SCN來讓flashback table回到之前的某個SCN狀態,

SQL> var scn number;
SQL> begin
  2    :scn := TIMESTAMP_TO_SCN(SYSTIMESTAMP);
  3  end;
  4  /

PL/SQL procedure successfully completed.

SQL> delete from t where x = 'PACKAGE';

1204 rows deleted.

SQL> select count(*) from t where x = 'PACKAGE';

  COUNT(*)
----------
         0

SQL> FLASHBACK TABLE t to SCN :scn;

Flashback complete.

SQL> select count(*) from t where x = 'PACKAGE';

  COUNT(*)
----------
      1204

SQL>

(3) flashback data, not structure

需要注意的是,flashback table只是恢復數據,並不會對錶的schema的變化有啥影響。

給表t增加一列new_column,

SQL> alter table t add new_column integer default 0;

Table altered.

SQL> update t set x = 'MODIFIED';

61883 rows updated.

SQL> commit;

Commit complete.

SQL> select * from t where rownum <= 10;

X                   NEW_COLUMN
------------------- ----------
MODIFIED                     0
MODIFIED                     0
MODIFIED                     0
MODIFIED                     0
MODIFIED                     0
MODIFIED                     0
MODIFIED                     0
MODIFIED                     0
MODIFIED                     0
MODIFIED                     0

10 rows selected.

flashback table到2分鐘之前,

SQL> flashback table t to timestamp (systimestamp - interval '2' minute);

Flashback complete.

SQL> select * from t where rownum <= 10;

X                   NEW_COLUMN
------------------- ----------
TABLE
INDEX
TABLE PARTITION
TABLE
INDEX
TABLE
INDEX
TABLE PARTITION
TABLE
INDEX

10 rows selected.

可以看到列x中的數據恢復到之前的狀態嗎,但是新增加的列new_column還是在的,並沒有消失(雖然該列的數據都沒有了)。

那麼Oracle是如何來實現這個flashback table的feature的呢?

可以通過下面的SQL語句查看新創建的數據對象有哪些,

SQL> select owner, object_name, object_type, temporary
  2  from dba_objects
  3  where created > trunc(sysdate);

OWNER                OBJECT_NAME   OBJECT_TYPE         T
-------------------- -------------------------------------------------------------------------
FRANK                SYS_TEMP_FBT
                                              TABLE                             Y
FRANK                FBT
                                              TABLE                             N
FRANK                T
                                              TABLE                             N

拋開表FBT不看(上一個部分中用到的這個表),除了表T,還有一個global temporary table SYS_TEMP_FBT. 這個表顯然是Oracle自己創建的。

該表結構如下,

SQL> desc SYS_TEMP_FBT;
Name
                                                                       Null?    Type
---------------------------------------------------------------------------------------------

SCHEMA
                                                                                VARCHAR2(32)
OBJECT_NAME
                                                                                VARCHAR2(32)
OBJECT#
                                                                                NUMBER
RID
                                                                                ROWID
ACTION
                                                                                CHAR(1)

其中一部分數據如下 (用Sample語句),

SQL> select * from sys_temp_fbt sample(0.01);

SCHEMA     OBJECT_NAM    OBJECT# RID                  A
---------- ---------- ---------- -------------------- -
FRANK      T               70534 AAAROGAAIAAAABKAGN   D
FRANK      T               70534 AAAROGAAIAAAABTAHc   I
FRANK      T               70534 AAAROGAAIAAAABVAHK   I
FRANK      T               70534 AAAROGAAIAAAABqAEX   I
FRANK      T               70534 AAAROGAAIAAAACOAA8   D
FRANK      T               70534 AAAROGAAIAAAAEPAEy   D
FRANK      T               70534 AAAROGAAIAAAAEbACE   I
FRANK      T               70534 AAAROGAAIAAAAEbACL   I
FRANK      T               70534 AAAROGAAIAAAAE2AKF   D
FRANK      T               70534 AAAROGAAIAAAAFDAEc   I

10 rows selected.

這個表中的數據是在進行flashback table操作的時候產生的。其實這個表(sys_temp_fbt)也是在第一次進行flashback table 操作的時候生成的。

SQL> select action, count(*) from sys_temp_fbt group by action;

A   COUNT(*)
- ----------
I      61883
D      61883

SQL> select count(*) from t;

  COUNT(*)
----------
     61883

根據Action (I -- insert, D-- Delete)的行數,可以看出,每次flashback table的時候,oracle會先把數據刪除,然後再重新插入之前時刻的數據(通過flashback query).

重新創建個小表來再看下,如下

SQL>

  1  create table test
  2  enable row movement
  3  as
  4   select rownum r
  5  from dual
  6* connect by rownum <= 10
SQL> /

Table created.

SQL> select * from test;

         R
----------
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10

10 rows selected.

刪除4條記錄,剩餘6條。 

SQL> delete from test where rownum < 5;

4 rows deleted.

SQL> commit;

Commit complete.

進行flashback table操作

SQL> flashback table test to timestamp systimestamp - interval '1' minute;

Flashback complete.

SQL> select * from test;

         R
----------
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10

10 rows selected.

SQL> select object_name, object_type, temporary from dba_objects
  2  where created > trunc(sysdate);

OBJECT_NAM OBJECT_TYPE         T
---------- ------------------- -
SYS_TEMP_F TABLE               Y
BT

TEST       TABLE               N
FBT        TABLE               N
T          TABLE               N

可以看出SYS_TMEP_FBT只存在一張,而且其中的數據隨着每次flashback table操作而重置。

SQL> select action, count(*) from sys_temp_fbt group by action;

A   COUNT(*)
- ----------
I         10
D          6

SQL> select * from sys_temp_fbt order by rid;

SCHEMA     OBJECT_NAM    OBJECT# RID                  A
---------- ---------- ---------- -------------------- -
FRANK      TEST            70724 AAARREAAIAAAACUAAA   I
FRANK      TEST            70724 AAARREAAIAAAACUAAB   I
FRANK      TEST            70724 AAARREAAIAAAACUAAC   I
FRANK      TEST            70724 AAARREAAIAAAACUAAD   I
FRANK      TEST            70724 AAARREAAIAAAACUAAE   D
FRANK      TEST            70724 AAARREAAIAAAACUAAE   I
FRANK      TEST            70724 AAARREAAIAAAACUAAF   D
FRANK      TEST            70724 AAARREAAIAAAACUAAF   I
FRANK      TEST            70724 AAARREAAIAAAACUAAG   D
FRANK      TEST            70724 AAARREAAIAAAACUAAG   I
FRANK      TEST            70724 AAARREAAIAAAACUAAH   D

SCHEMA     OBJECT_NAM    OBJECT# RID                  A
---------- ---------- ---------- -------------------- -
FRANK      TEST            70724 AAARREAAIAAAACUAAH   I
FRANK      TEST            70724 AAARREAAIAAAACUAAI   D
FRANK      TEST            70724 AAARREAAIAAAACUAAI   I
FRANK      TEST            70724 AAARREAAIAAAACUAAJ   D
FRANK      TEST            70724 AAARREAAIAAAACUAAJ   I

16 rows selected.

SQL>

可以看到對每行記錄都是先進行刪除,然後再插入。

最大疑問: 爲什麼需要這張SYS_TEMP_FBT來記錄flashback table的操作呢? 我想完全可以在執行flashback table的時候,首先把該表中的數據全部刪除,然後插入flashback query得到的數據。待研究研究……

(3) Flashback drop

可以用Flashback drop來恢復一個被刪除的表,

SQL> drop table test;

Table dropped.

SQL> flashback table test to before drop;

Flashback complete.

SQL> select * from test;

         R
----------
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10

10 rows selected.

(4) Recycle bin

從Oracle10g開始,用drop刪除的數據庫對象並沒有真正從數據庫中刪除掉,而是被放到了recycle bin中了,也是藉此,flashback table to before drop纔可以work.

SQL> DESC recyclebin
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 OBJECT_NAME                               NOT NULL VARCHAR2(30)
 ORIGINAL_NAME                                      VARCHAR2(32)
 OPERATION                                          VARCHAR2(9)
 TYPE                                               VARCHAR2(25)
 TS_NAME                                            VARCHAR2(30)
 CREATETIME                                         VARCHAR2(19)
 DROPTIME                                           VARCHAR2(19)
 DROPSCN                                            NUMBER
 PARTITION_NAME                                     VARCHAR2(32)
 CAN_UNDROP                                         VARCHAR2(3)
 CAN_PURGE                                          VARCHAR2(3)
 RELATED                                   NOT NULL NUMBER
 BASE_OBJECT                               NOT NULL NUMBER
 PURGE_OBJECT                              NOT NULL NUMBER
 SPACE                                              NUMBER

SQL> drop table test;

Table dropped.

SQL> flashback table test to before drop rename to test_t;

Flashback complete.

SQL> select * from test_t;

         R
----------
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10

10 rows selected.

4. Flashback Restore Points in Oracle 10g R2 (參考Adrian Billington的 flashback restore point in 10.2

Oracle 10g R1 引入了flashback table, 可以通過SCN或Timestamp來進行數據的恢復或者undrop被刪除的表。10g R2引入了Restore Point來提供另外一種flashback table 的方式。

(1) Restore Points

Restore points, 說白了,就是你定義一個容易記住的名字來標示你將來想讓表flashback到什麼地方,因爲SCN, timestamp相對來說更不容易記憶,不直觀。但Oracle最終還是根據SCN來做flashback。

根據文檔說明,可以創建最多2048個命名的resotred points. restore points 可以是 normal 或 guaranteed.  Guaranteed的restore point用在flashback dabatase中。

(2) Privileges

創建restore point需要以下權限,

SELELCT ANY DICTIONARY

FLASHBACK ANY TABLE

(3) 準備數據

SQL> drop table t;

Table dropped.

SQL> create table t(x, y, z)
  2  enable row movement
  3  as
  4    select object_id, object_name, object_type
  5    from all_objects
  6    where rownum <= 5;

Table created.

SQL> select * from t;

         X Y                              Z
---------- ------------------------------ ----------------
        20 ICOL$                          TABLE
        44 I_USER1                        INDEX
        28 CON$                           TABLE
        15 UNDO$                          TABLE
        29 C_COBJ#                        CLUSTER

(4) Creating and Using a restore point

創建一個restore point – before_we_do_anything

SQL> create restore point before_we_do_anything;

Restore point created.

先刪除2條數據,並commit.
SQL> delete from t where rownum <= 2;

2 rows deleted.

SQL> commit;

Commit complete.

SQL> select * from t;

         X Y                              Z
---------- ------------------------------ -------------------
        28 CON$                           TABLE
        15 UNDO$                          TABLE
        29 C_COBJ#                        CLUSTER

現在用restore point來flashback table.

SQL> flashback table t to restore point before_we_do_anything;

Flashback complete.

SQL> select * from t;

         X Y                              Z
---------- ------------------------------ -------------------
        20 ICOL$                          TABLE
        44 I_USER1                        INDEX
        28 CON$                           TABLE
        15 UNDO$                          TABLE
        29 C_COBJ#                        CLUSTER

刪除restore point before_we_do_anything.

SQL> drop restore point before_we_do_anything;

Restore point dropped.

(5) Metadata

注意restore point並不是一個database object,從視圖dba_objects裏面是查不到的。但是Oracle提供了一個動態視圖v$restore_point來查看restore point的信息。

SQL> desc v$restore_point;
Name
                                                                       Null?    Type
---------------------------------------------------------------------------------------------
SCN
                                                                                NUMBER
DATABASE_INCARNATION#
                                                                                NUMBER
GUARANTEE_FLASHBACK_DATABASE
                                                                                VARCHAR2(3)
STORAGE_SIZE
                                                                                NUMBER
TIME
                                                                                TIMESTAMP(9)
NAME
                                                                                VARCHAR2(128)

SQL>

(6) Retention target

參數db_flashback_retention_target決定可以恢復到多久之前的restore point。

Normal restore point 在超過參數control_file_record_keep_time設置的時間後會被自動刪除 (guaranteed restore point需要手動來刪除)

SQL> show parameter DB_FLASHBACK_RETENTION_TARGET

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_flashback_retention_target        integer     1440

SQL> show parameter CONTROL_FILE_RECORD_KEEP_TIME

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
control_file_record_keep_time        integer     7
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章