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 來拯救資料了。



沒有留言:

張貼留言