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



2022年4月29日 星期五

7. Switchover and Failover

Data Guard 的角色切換可以分為 Switchover 與 Failover 兩種, Switchover 指的是 Primary 與 Standby 的角色互換,例如原本的 Primary 為 orcl 、 Standby 為 orcls ,在進行完 Switchover 之後 Primary 變為 orcls 、 Standby 變為 orcl ,並且繼續同步,不會破壞原本 Data Guard 的機制, Switchover 使用上都是有計畫性的,例如 Primary 需要停機做維護,此時不想讓服務停止太久就可以使用 Switchover 將 Standby 轉換為 Primary 並且將服務導向這邊,等到原本的 Primary 維護完成後再切換回來; Failover 指的是直接將 Standby Activate 起來,使用的時機是在 Primary 無法使用時,將 Standby 緊急轉換為新的 Primary 所用,這種情況大多都是未預期事件所造成, Failover 會切斷原本 Primary 與 Standby 的同步機制,當 Standby 轉換為新的 Primary 之後就無法再接續同步,進行完 Failover 之後, Data Guard 的架構要重新建立。 Switchover 與 Failover 同樣是把 Standby 轉換為 Primary ,其中最大的差別就是 Switchover 不會破壞 Data Guard 的同步,而 Failover 則是會破壞 Data Guard 的架構。


  • Switchover

進行 Switchover 需要到 Primary 與 Standby 分別進行操作,如果是 RAC Database 的話,須先將其它的 Instance 停下,只留下一個 Instance 進行操作,首先將原本的 Primary 轉換為 Standby 並且重啟至 mount 狀態 :

SQL> alter database commit to switchover to physical standby;

SQL> shutdown immediate

SQL> startup mount


然後再到原本的 Standby 進行轉換為 Primary ,並且將資料庫 open :

SQL> alter database commit to switchover to primary;

SQL> alter database open;


完成 Switchover 切換後可以從 v$database 確認資料庫是屬於哪一個角色 :

SQL> select database_role from v$database;


確認完成後於新的 Standby 開啟 MRP 繼續進行同步。


如果有使用 Data Guard Broker 的話, Switchover 只需要一個簡單的命令就可以完成,例如原本的 Primary 為 orcl 、 Standby 為 orcls ,透過 Broker 將 orcls 轉為 Primary 、 orcl 轉為 Standby :

$ dgmgrl sys/welcome1@orcl

DGMGRL> switchover to 'orcls';


完成後以 show configuration 確認即可,這邊要注意的是,登入 dgmgrl 必須要提供完整的 sys 使用者名稱與密碼,如果沒有提供密碼,那麼 Broker 就無法登入到資料庫完成重啟的動作,此時就必須再回到上述 SQL*Plus 的操作來完成。


在 Oracle 12c 之後, SQL*PLUS 對於 Switchover 的命令進行簡化,只需要在 Primary 執行一個命令即可 :

SQL> alter database switchover to orcls verify;

   (使用 verify 先進行切換前檢查)

SQL> alter database switchover to orcls;

   (實際進行切換)


這個命令在執行了 switchover 之後, Primary 與 Standby 的角色就會進行互換,最後需要做的是將新的 Standby (原本的 Primary) 重啟到 mount 、新的 Primary (原本的 Standby) 將其 open 。


  • Failover

進行 Failover 等於是把 Primary 與 Standby 的關係切斷,直接將 Standby 變成 Primary 開起來用,一般都是在 Primary 不可用時且非得以的情況下才會進行 Failover ,由於 Primary 已不可用,所以 Failover 操作上只需在 Standby 端進行,首先將 MRP 停止並且執行 Finish 的動作 :

SQL> alter database recover managed standby database cancel;

SQL> alter database recover managed standby database finish force;


執行了 Finish 動作表示告訴 Data Guard 即將要執行 Failover ,它會 Apply 當下 Standby Redo Log 所有的資料並且切斷 RFS ,一旦執行了 Finish 就無法再重新啟動 MRP 了, Finish 之後就可以將 Standby Activate 起來並且 open ,完成 Failover 的操作 :

SQL> alter database activate standby database;

SQL> alter database open;


如果是使用 Data Guard Broker ,那麼只需連線到 Standby 執行簡單的 Failover 指令即可 :

$ dgmgrl sys/welcome1@orcls

DGMGRL> failover to 'orcls';


執行了 Failover 之後, Primary 與 Standby 的關係就會被切斷,若要還原成原本的 Data Guard 架構就必須要重建 Standby 。


2022年4月25日 星期一

6. Snapshot Standby

Snapshot Standby 是 Oracle 11g 開始有的新功能,主要是可以將 Standby Database 開啟為 read / write 模式又不會破壞原本 Data Guard 的機制,傳統的 Standby Database 都是處於 mount 狀態下進行 Log Apply ,即便是 open 也只能在唯讀 (read only) 模式,對於有讀寫需求的 Application 就無法在 Standby Database 上進行測試或者是驗證 Standby 的資料與功能,而 Snapshot Standby 就可以解決這個問題。


以往建立的 Standby Database 總會讓人有個疑問,懷疑這個 Standby 的功能是否正常,資料是否正確,萬一有天 Primary 發生問題時, Standby Database 是否可以馬上承接所有的業務 ? 而 Snapshot Standby 正好可以將 Standby 開啟為 read / write 模式進行這些驗證,等到驗證完畢後再還原回原本的 Physical Standby 繼續進行 Data Guard 的同步,不僅可以消除對 Standby Database 的顧慮,同時也不會破壞原本 Data Guard 的機制,可以說是一舉兩得的功能。


Snapshot Standby 開啟為 read / write 模式又不會破壞原本的 Data Guard 機制,主要是使用資料庫 Flashback 的特性來達到這個目的,在 Standby Database 轉換為 Snapshot Standby 的同時,會自動 Enable Flashback Database 的功能,並且同時建立 Restore Point ,在 Snapshot Standby 轉換回 Physical Standby 時,就會使用 Flashback Database 這個功能將 Standby Flashback 回到 Restore Point ,然後再從 Restore Point 這個時間點繼續進行 Data Guard 的同步,由於使用了 Flashback ,所以在 Snapshot Standby 開啟為 read / write 時的所有異動都會被還原,也因此不會影響到原本 Data Guard 的同步。


將 Physical Standby 轉換為 Snapshot Standby 只需要幾個簡單的命令就可以完成,由於會啟用 Flashback Database 功能,所以先要確認 Recovery Area 的相關參數是否已經設置 :


準備完成後就可以停止 MRP :

SQL> alter database recover managed standby database cancel;


然後執行轉換至 Snapshot Standby ,並且將 Database Open :

SQL> alter database convert to snapshot standby;

SQL> alter database open;


轉換完成後可以由 v$database 查得 Database Role 為 Snapshot Standby 並且為 Read Write 模式:


轉換回 Physical Standby 必須將 Standby 重啟至 mount 狀態進行轉換,完成後再啟動 MRP :

SQL> shutdown immediate

SQL> startup mount

SQL> alter database convert to physical standby;

SQL> alter database recover managed standby database disconnect;


如果是使用 Data Guard Broker ,只需簡單執行 convert 動作就好 :

DGMGRL> convert database 'orcls' to snapshot standby;

  (轉換 orcls 為 snapshot standby)


DGMGRL> convert database 'orcls' to physical standby;

  (轉換 orcls 回 physical standby)


使用 Data Guard Broker 執行轉換之後,由 show configuration 可以看到 orcls 的角色變為 Snapshot Standby :


最後要注意的是,由於 Snapshot Standby 使用的是 Flashback Database 功能,因此開啟後的異動要注意 Recovery Area 的空間是否足夠容納 Flashback Log ,當開啟時間越久以及異動量越大,那麼 Recovery Area 需要的空間就越大,由於 Snapshot Standby 使用的是 Guarantee Restore Point ,所以當 Recovery Area 空間不足時就無法再進行任何操作了。