2022年5月4日 星期三

2. Flashback Data Archive

Flashback Data Archive (又稱為 Total Recall) 是基於 Flashback Query 應用的一種技術,在資料還沒有被刷出 Undo 之前都可以利用 Flashback Query 來查得,但如果已經不再 Undo 裡面,除了倒備份,否則就無法再查到這些舊資料,從這邊就衍生出一個想法,如果可以定時的把舊資料存放下來,那麼即使它已經不在 Undo ,我們依然可以查詢得到這些歷史資料,這就是 Flashback Data Archive 的用途。 Flashback Data Archive 會自動的將 Table 異動的歷史資料存放下來,未來就可以使用 as of timestamp 這種 Flashback Query 的語法來查詢歷史資料,這樣 Flashback Query 能回溯查詢的時間點就不用受限於 Undo Retention ,而是 Flashback Data Archive 自己可以決定這些舊資料要保留多久。


建立 Flashback Data Archive 使用 create flashback archive 指令來建立,例如建立一個名稱為 fla1 的 Flashback Data Archive ,賦予 Tablespace 的 Quota 為 10M ,資料保留期限為 1 年 :

SQL> create flashback archive fla1 tablespace fla quota 10M retention 1 year;

如果要將這個 Flashback Data Archive 物件設定為 Default ,則在建立的時候使用 Default 選項來建立 :

SQL> create flashback archive default fla1 tablespace fla quota 10M retention 1 year;


建立完 Flashback Data Archive 之後,接下來賦予使用者可以使用的權限,例如賦予 HR 使用者可以使用 fla1 這個 Flashback Data Archive 的權限:

SQL> grant flashback archive administer to hr;

SQL> grant flashback archive on fla1 to hr;


權限賦予後,就可以設定哪些 Table 要使用 Flashback Data Archive 的功能,例如將 HR.REGIONS 這個 Table 啟用 Flashback Data Archive :

SQL> alter table hr.regions flashback archive fla1;


HR.REGIONS 啟用了 Flashback Data Archive 之後,只要有更新資料,舊歷史資料就會存放下來,在 fla1 的保留期間 1 年內都可以使用 Flashback Query 查到 HR.REGIONS 的歷史資料,例如將 regions_id=2 改為 Unite States :


更改後可以使用 Flashback Query 查到更新前的歷史資料為 Americas ,只要是在 fla1 保留期間 1 年內的資料都可以查到:


Flashback Data Archive 的維護可以使用 alter 指令來操作 :

SQL> alter table hr.regions flashback archive fla1;

      (Table hr.regions 啟用 Flashback Data Archive)

SQL> alter table hr.regions no flashback archive;

      (Table hr.regions 停用 Flashback Data Archive)

SQL> alter flashback archive fla1 add tablespace tbs3 quota 5G;

      (為 Flashback Data Archive fla1 添加一個 Tablespace 空間)

SQL> alter flashback archive fla1 modify retention 2 year;

      (變更 Flashback Data Archive fla1 保留期間為 2 年)

SQL> alter flashback archive fla1 purge before timestamp(systimestamp – interval '1' day);

      (刪除 Flashback Data Archive fla1 一天前的資料)

SQL> drop flashback archive fla1;

      (刪除整個 Flashback Data Archive fla1)


檢查 Flashback Data Archive 的設定可以透過 dba_flashback_archive 、 dba_flashback_arcihve_ts 、 dba_flashback_archive_tables 等來查詢,最後要注意的是 Flashback Data Archive 所使用的 Tablespace 空間是否足夠,尤其是 DML 頻率很頻繁的 Table 對於空間的使用量較大,如果空間不夠,那麼 Flashback Archive 的動作就無法完成並出現 ORA-55623 、 ORA-55617 等錯誤,若啟用 Flashback Data Archive 的 Table 它的 Flashback Archive 動作無法完成,那麼 Table 本身的 DML 也會無法完成,所以為了避免影響到原生的 Table ,必須要注意 Flashback Data Archive 空間的使用。


2022年5月3日 星期二

1. Flashback Query

Flashback Query 是基於 Undo 應用上的一項技術,在進行 DML 的同時,資料變更前的 Before Image 會存放一份在 Undo Tablespace 裡面,即便已經執行了 commit ,這些資料仍然會停留在 Undo Tablespace 裡面一陣子,在資料沒有被刷出 Undo 之前,我們都還可以查詢的到,這就是所謂的 Flashback Query ,例如早上 10:00 不小心執行了錯誤的 update 導致資料錯誤,這時候就可以利用 Flashback Query 查詢 10:00 前的資料,並且再將它更新回來。


Flashback Query 最早於 Oracle 9i 開始可以使用,只要資料還沒有被刷出 Undo ,就可以利用 as of timestamp 語法查詢的到,除此之外 Flashback Query 還有另外兩種進階的功能, Flashback Version Query 與 Flashback Transaction Query 。例如原本 regions 這個 Table 總共有四筆資料 :


現在將 region_id = 2 與 region_id = 3 的資料進行 update :


接下來運用 Flashback Query 的技術來查詢被更新前的資料 :


  • Flashback Query 

使用 as of timestamp 語法來查詢更新前的資料:

SQL> select * from regions as of timestamp

 to_timestamp('20220503 08:45:00','yyyymmdd hh24:mi:ss');


在查到原本的資料後就可以再使用 update 語法將資料更新回來,更進一步可以建立一個 Table 將這些資料存放下來,這樣可以更容易比對更新前後的資料 :

SQL> create table regions_old as select * from regions as of timestamp

 to_timestamp('20220503 08:45:00','yyyymmdd hh24:mi:ss');


  • Flashback Version Query

使用的是 versions 語法,不同於 Flashback Query 的是, Version Query 可以查詢一個區間的異動,並且每個異動會賦予一個 versions_xid ,同時也會有異動的時間 :

SQL> select versions_xid,versions_starttime,versions_endtime,region_id,region_name

        from regions versions between timestamp

         to_timestamp('20220503 08:45:00','yyyymmdd hh24:mi:ss') and

   to_timestamp('20220503 08:50:00','yyyymmdd hh24:mi:ss');


透過 Version Query 可以知道在 08:48:03 這個時間點, region_id 為 2 與 3 的資料被異動了。


  • Flashback Transaction Query

使用 flashback_transaction_query 這個 Table 查詢整個 Transaction 的 Undo SQL ,資料庫必須 enable supplemental log 才可以使用 Transaction Query :

SQL>  alter database add supplemental log data;


由 Version Query 查詢到 versions_xid 之後,就可以由 flashback_transaction_query 直接得到整個 Transaction 的 Undo SQL :

SQL>  select table_name,undo_sql from flashback_transaction_query 

where xid='03000500E5A70200';


得到 Undo SQL 之後可以直接執行將資料更新回來,或者是使用 dbms_flashback.transaction_backout 直接將整個 Transaction 的資料還原 :

SQL>  exec dbms_flashback.transaction_backout(1,sys.xid_array('03000500E5A70200'));


在進行了 transaction_backout 之後,可以經由 dba_flashback_txn_state 與 dba_flashback_txn_report 來查詢 Flashback Transaction Report :

SQL>  select a.xid,b.xid_report 

from dba_flashback_txn_state a, dba_flashback_txn_report b

       where a.compensating_xid=b.compensating_xid

         and a.xid='03000500E5A70200';


Flashback Query 是一個很好用的功能,尤其是發生人為操作失誤的時候,可以緊急的使用 Flashback Query 將資料還原,但這個操作必須是 DML 才行,如果是 DDL 例如 Truncate 指令就無法使用 Flashback Query 來拯救資料了。