1. 程式人生 > >[Oracle] Data Guard 系列(2)

[Oracle] Data Guard 系列(2)

Oracle Data Guard從巨集觀上來說,主要提供以下兩個服務:

1)日誌傳輸:主庫把生成的Redo日誌傳輸至備庫;

2)日誌應用:備庫應用從主庫傳輸過來的Redo日誌。

本文先介紹其中的日誌傳輸服務,日誌應用服務在下節《Data Guard 系列(3) - 日誌應用》介紹。

1. 日誌傳輸方式

有兩種日誌傳輸方式(ARC和LGWR),第一種是採用ARC程序傳輸日誌,其示意圖如下:


                                                   注:上圖來自《大話Oracle RAC》

其大致過程如下:

1)主庫:日誌先寫入線上重做日誌,當線上重做日誌滿後(或人為切換), ARC0程序歸檔該日誌至主庫本地歸檔目錄,歸檔完成後,ARC1馬上將該歸檔日誌傳輸到備庫;

2)備庫:RFS程序接收日誌,如果備庫有Standby重做日誌,則把日誌複製到Standby重做日誌,接著把Standby重做日誌歸檔至備庫本地歸檔目錄,最後應用歸檔日誌;如果沒有配置Standby重做日誌,RFS程序接收日誌後,直接把它放到備庫的歸檔目錄下,再應用該日誌。

另外一種是使用LGWR程序傳輸日誌,它又分為兩種方式,分別是ASYNC和SYNC,下面是ASYNC的示意圖:


下面是SYNC的示意圖如下:


                                                                  注:上圖來自《大話Oracle RAC》

用LGWR傳輸大致如下:

1)主庫:只要有新的重做日誌產生,LGWR程序將觸發LNSn程序把新生成的日誌傳輸到備庫(注意:這裡不能由LGWR直接傳輸,因為整個資料庫例項只有一個LGWR,為了保證它的主要業務效能不受影響,不能由它直接傳輸);

2)備庫:RFS程序接收到日誌後,將其寫入Standby重做日誌,如果備庫開啟了實時應用,就立即做日誌應用,如果沒有開啟,則等Standby重做日誌歸檔後再應用。

3)其中,ASYNC和SYNC的區別在於:SYNC是在redo還在記憶體時,LNSn程序就開始傳輸,而ASYNC是在redo緩衝到online redo log後,LNSn才開始傳輸。

從上面可以得出,從同步的實時性來看,LGWR(SYNC) > LGWR(ASYNC)> ARCH

2. 日誌傳送的配置

主庫的日誌傳送是由log_archive_dest_n引數設定(注意:同時還有一個和它相對應的開關引數log_archive_dest_state_n,用於指定該引數是否有效),下面簡單介紹下該引數各個屬性的含義。

SERVICE(必須):指定備庫的網路連線名;

SYNC/ASYNC(預設為ASYNC):指定日誌的傳輸模式(同步/非同步);

NET_TIMEOUT:指定當採用SYNC傳輸模式時,超過多少秒則表示網路超時(預設為30s),在使用SNYC模式時,強烈建議設定改引數;

AFFIRM/NOAFFIRM:AFFIRM表示只有當日志寫入Standby重做日誌後才算日誌傳輸成功,NOAFFIRM則沒有這個要求;

DB_UNIQUE_NAME:指定備庫的DB_UNIQUE_NAME;

VALID_FOR:格式為(redo_log_type,database_role),只有這兩個條件全部符合,才會傳送日誌;

   其中redo_log_type有如下取值:ONLINE_LOGFILE, STANDBY_LOGFILE, ALL_LOGFILES

       database_role有如下取值:PRIMARY_ROLE, STANDBY_ROLE, ALL_ROLES

REOPEN:指定當連線錯誤發生時,多少秒之後重試;

COMPRESSION:指定是否對日誌進行壓縮,已提高網路傳輸效能。

下面是log_archive_dest_n的一個例子:

DB_UNIQUE_NAME=BOSTON
LOG_ARCHIVE_CONFIG='DG_CONFIG=(BOSTON,CHICAGO,HARTFORD)' 
LOG_ARCHIVE_DEST_2='SERVICE=CHICAGO ASYNC NOAFFIRM VALID_FOR=(ONLINE_LOGFILE, 
PRIMARY_ROLE) REOPEN=60 COMPRESSION=ENABLE  DB_UNIQUE_NAME=CHICAGO' 
LOG_ARCHIVE_DEST_STATE_2='ENABLE' 
LOG_ARCHIVE_DEST_3='SERVICE=HARTFORD SYNC AFFIRM NET_TIMEOUT=30 
VALID_FOR=(ONLINE_LOGFILE,PRIMARY_ROLE) REOPEN=60 COMPRESSION=ENABLE   
DB_UNIQUE_NAME=HARTFORD' 
LOG_ARCHIVE_DEST_STATE_3='ENABLE'

3. 日誌接受的配置

在備庫,當RFS程序接受到日誌後,就將其寫入Standby日誌檔案裡,備庫的Standby日誌檔案可以看做是主庫線上日誌檔案的一個映象,當主庫做日誌切換時,備庫的Standby日誌也做相應的切換,切換後的Standby日誌由備庫的ARCH程序歸檔。 Oracle規定備庫的Standby日誌檔案大小不能小於主庫線上日誌檔案最大的一個,一般情況下,為了管理方便,最好把所有的線上日誌和Standby日誌大小設為一樣。 Oracle還規定備庫的Standby日誌檔案至少要比主庫的線上日誌檔案多一組。 通過下面語句可以查詢主庫線上日誌的大小和組數:
SQL> SELECT GROUP#, BYTES FROM V$LOG;
通過下面的語句可以查詢備庫Standby日誌的大小和組數:
SQL> SELECT GROUP#, BYTES FROM V$STANDBY_LOG;
假設主庫有兩組線上日誌,每個日誌檔案大小為500M,那麼我們至少需要3組Standby,且每個日誌檔案大小不少於500M:
SQL> ALTER DATABASE ADD STANDBY LOGFILE ('/oracle/dbs/slog1.rdo') SIZE 500M;
 
SQL> ALTER DATABASE ADD STANDBY LOGFILE ('/oracle/dbs/slog2.rdo') SIZE 500M;
 
SQL> ALTER DATABASE ADD STANDBY LOGFILE ('/oracle/dbs/slog3.rdo') SIZE 500M;

上面提到過,備庫的Standby日誌也會被歸檔,它的歸檔路徑由備庫的log_archive_dest_n引數的location屬性設定,如下所示:

LOG_ARCHIVE_DEST_1 = 'LOCATION = /disk2/archive
VALID_FOR=(STANDBY_LOGFILE,STANDBY_ROLE)'
LOG_ARCHIVE_DEST_STATE_2=ENABLE

4. 日誌傳輸狀態的監控

第一步:在主庫執行如下語句獲得最新歸檔序列號:

SQL> SELECT MAX(SEQUENCE#), THREAD# FROM V$ARCHIVED_LOG GROUP BY THREAD#;

第二步:在主庫執行如下語句確認最新歸檔的日誌是否已經傳輸至備庫:

SQL> SELECT DESTINATION, STATUS, ARCHIVED_THREAD#, ARCHIVED_SEQ# FROM V$ARCHIVE_DEST_STATUS 
> WHERE STATUS <> 'DEFERRED' AND STATUS <> 'INACTIVE';
 
DESTINATION         STATUS  ARCHIVED_THREAD#  ARCHIVED_SEQ#
------------------  ------  ----------------  -------------
/private1/prmy/lad   VALID                 1            947
standby1             VALID                 1            947
如果狀態不是VALID,則說明日誌傳輸失敗。

5. 手動解決日誌傳輸GAP

Oracle DG會自動檢測日誌傳輸GAP並自動解決,但有時候GAP無法自動解決,必須DBA人工干預,下面我們講講手動解決的步驟:

首先,在備庫執行下列語句查詢是否有GAP:

SQL> SELECT * FROM V$ARCHIVE_GAP;

    THREAD# LOW_SEQUENCE# HIGH_SEQUENCE#
-----------  -------------  --------------
          1              7              10
HIGH_SEQUENCE#減去LOW_SEQUENCE#就是當前的GAP數,上例顯示備庫缺少從7到10(不包含10)的歸檔日誌。

接著,在主庫查詢這些歸檔日誌的目錄位置:

SQL> SELECT NAME FROM V$ARCHIVED_LOG WHERE THREAD#=1 AND DEST_ID=1 AND SEQUENCE# BETWEEN 7 AND 10;

NAME
--------------------------------------------------------------------------------
/primary/thread1_dest/arcr_1_7.arc 
/primary/thread1_dest/arcr_1_8.arc 
/primary/thread1_dest/arcr_1_9.arc

把這些歸檔日誌從主庫拷貝至備庫,並在備庫上註冊:

SQL> ALTER DATABASE REGISTER LOGFILE  '/physical_standby1/thread1_dest/arcr_1_7.arc';

SQL> ALTER DATABASE REGISTER LOGFILE  '/physical_standby1/thread1_dest/arcr_1_8.arc';

SQL> ALTER DATABASE REGISTER LOGFILE  '/physical_standby1/thread1_dest/arcr_1_9.arc';