忘れかけのIT備忘録

今まで学んできた知識や小技、なるほど!と思ったことをメモするブログです。

Data Guardのフェイルオーバー/フェイルバック検証(その1)

Data Guardのフェイルオーバー/フェイルバックについて、机上の知識はあるものの、実務経験が無いため、実際の動きを検証しました。

フェイルオーバーは、プライマリDBをData Guard構成から切り離し、スタンバイDBをプライマリDBにロール変更(昇格)させます。
プライマリ側のシステム障害など、プライマリ側のデータベースが使用できない場合、スタンバイDBをプライマリDBに昇格させることでユーザがデータベースへアクセスできなくなることを回避します。
スイッチオーバーとの大きな違いはロール入れ替え・変更の目的が計画的かそうじゃないかですね。

プライマリ側のシステム復旧後、旧プライマリDBと新プライマリDB(昇格後のプライマリDB)でData Guard再構成し、スイッチオーバーすることで障害発生前の状態に戻せます。
旧プライマリDBの復旧方法は「フラッシュバックDB方式」と「リストア/不完全リカバリ方式」があります。
本検証ではフェイルオーバー後、「フラッシュバックDB方式」と「リストア/不完全リカバリ方式」でそれぞれフェイルバックしてみます。

なお、プライマリ側のシステム障害検知後、自動的にフェイルオーバーする「ファスト・スタート・フェイルオーバー」という機能もあります。
※本検証は手動フェイルオーバーで、ファスト・スタート・フェイルオーバーは対象外です

【補足】
ファスト・スタート・フェイルオーバーを使用する場合、Data Guard Broker構成後、オブザーバ(プライマリDBとスタンバイDBを管理・監視するサーバ)が必要です
オブザーバは下記のいずれかが必要です
a. Oracle Client Administrator(完全インストール)
b. Oracle Database Enterprise Edition/Personal Edition
※Enterprise Managerでオブザーバプロセスを管理する場合、Agentが必要ですが「a.」だとAgentはインストールされないため、個別でインストールが必要です

Oracle Data Guardのインストール

■検証環境、前提、設定情報
Data Guardのスナップショット・スタンバイ検証 - 忘れかけのIT備忘録 と同様
※フェイルオーバーは手動フェイルオーバーで実施します

■検証パターン
①手動フェイルオーバー
②フェイルバック(フラッシュバックDB)

■検証
①手動フェイルオーバー
プライマリDBでデータ破損(論理障害)が発生した場合を想定し、手動フェイルオーバーして現行のスタンバイDBがプライマリロールに昇格できるか検証します
※プライマリDBが稼働しているパターン

【検証手順】
1. [現プライマリDB]フラッシュバックDB有効化
2. [現プライマリDB]インスタンス1のみMOUNTモードで起動
3. [現プライマリDB]未送信のREDOデータをフラッシュ
4. [現プライマリDB/現スタンバイDB]アーカイブログの順序番号の最大値取得
5. [現スタンバイDB]アーカイブログギャップ取得
6. [現スタンバイDB]MRP停止
7. [現スタンバイDB]手動フェイルオーバー
8. [新プライマリDB]OCRのロール、開始オプション変更
9. [新プライマリDB]DB再起動

【想定】
フェイルオーバー後、現スタンバイDB(orcldr)のロールがプライマリロールになること

【検証結果】
フェイルオーバー後、現スタンバイDB(orcldr)のロールがプライマリロールになった

【作業ログ】

1. [現プライマリDB]フラッシュバックDB有効化
フェイルバックはフラッシュバックDBを使用するため、事前にフラッシュバックログを取得するようにします

SQL> select flashback_on from v$database;

FLASHBACK_ON
------------------------------------------------------
NO

SQL> alter database flashback on;

データベースが変更されました。

SQL> select flashback_on from v$database;

FLASHBACK_ON
------------------------------------------------------
YES

2. [現プライマリDB]インスタンス1のみMOUNTモードで起動
インスタンスが起動している場合、後続の「3.」の「alter system flush redo to orcldr;」文が失敗するため、インスタンス1のみMOUNTモードで起動します

[oracle@node1 ~]$ srvctl status database -db orcl
インスタンスorcl1はノードnode1で実行中です。
インスタンスorcl2はノードnode2で実行中です。
[oracle@node1 ~]$ srvctl stop database -db orcl
[oracle@node1 ~]$ srvctl status database -db orcl
インスタンスorcl1はノードnode1で実行されていません。
インスタンスorcl2はノードnode2で実行されていません。
[oracle@node1 ~]$ srvctl start instance -db orcl -instance orcl1 -startoption mount
[oracle@node1 ~]$ srvctl status database -db orcl
インスタンスorcl1はノードnode1で実行中です。
インスタンスorcl2はノードnode2で実行されていません。

3. [現プライマリDB]未送信のREDOデータをフラッシュ
未送信のREDOデータをプライマリDBからスタンバイDBにフラッシュします
データロストの発生を回避します

SQL> alter system flush redo to orcldr;

システムが変更されました。

【参考】
1つのインスタンス以外が起動しているとエラー
SQL> alter system flush redo to orcldr;
alter system flush redo to orcldr
*
行1でエラーが発生しました。:
ORA-38777: 他のインスタンスでデータベースを起動しないでください

インスタンスがオープンだとエラー
SQL> alter system flush redo to orcldr;
alter system flush redo to orcldr
*
行1でエラーが発生しました。:
ORA-16445: データベースはマウントする必要があり、オープンできません

4. [現プライマリDB/現スタンバイDB]アーカイブログの順序番号の最大値取得
プライマリDBとスタンバイDBのアーカイブログの順序番号が一致しているか(同期が取れているか)確認します
一致していない(同期が取れていない)場合、プライマリDBのアーカイブログをスタンバイDBにコピー・登録します

現プライマリDB
SQL> select thread#, max(sequence#) from v$archived_log group by thread#;

   THREAD# MAX(SEQUENCE#)
---------- --------------
         1            115
         2            111

現スタンバイDB
SQL> select thread#, max(sequence#) from v$archived_log group by thread#;

   THREAD# MAX(SEQUENCE#)
---------- --------------
         1            115
         2            111

※今回は一致しているため、スタンバイDBにコピー・登録は割愛します

5. [現スタンバイDB]アーカイブログギャップ取得
スタンバイDBでアーカイブログのギャップ(不足)が発生しているか確認します
ギャップが発生している場合、プライマリDBのアーカイブログをスタンバイDBにコピー・登録します

SQL> select * from v$archive_gap;

レコードが選択されませんでした。

※今回は発生していないため、スタンバイDBにコピー・登録は割愛します

6. [現スタンバイDB]MRP停止
SQL> select client_process, process, thread# ,sequence# ,status from v$managed_standby where process = 'MRP0';

CLIENT_PROCESS       PROCESS                 THREAD#  SEQUENCE# STATUS
-------------------- -------------------- ---------- ---------- --------------------
N/A                  MRP0                          2        112 WAIT_FOR_LOG

SQL> alter database recover managed standby database cancel;

データベースが変更されました。

SQL> select client_process, process, thread# ,sequence# ,status from v$managed_standby where process = 'MRP0';

レコードが選択されませんでした。

7. [現スタンバイDB]手動フェイルオーバー
SQL> select db_unique_name, database_role from v$database;

DB_UNIQUE_NAME       DATABASE_ROLE
-------------------- ------------------------------------------------
orcldr               PHYSICAL STANDBY

SQL> alter database failover to orcldr;

データベースが変更されました。

SQL> select db_unique_name, database_role from v$database;

DB_UNIQUE_NAME       DATABASE_ROLE
-------------------- ------------------------------------------------
orcldr               PRIMARY

8. [新プライマリDB]OCRのロール、開始オプション変更
OCRに登録されている開始オプションとロールはスタンバイ時の状態のため、手動でプライマリ用に変更します

[oracle@dr-node1 ~]$ srvctl config database -db orcldr
一意のデータベース名: ORCLDR
データベース名: ORCLDR
Oracleホーム: /u01/app/oracle/product/12.1.0/dbhome_1
Oracleユーザー: oracle
spfile: +DATA/ORCLDR/PARAMETERFILE/spfileORCLDR.ora
パスワード・ファイル: +DATA/ORCLDR/PASSWORD/orapwORCLDR
ドメイン
開始オプション: mount
停止オプション: immediate
データベース・ロール: PHYSICAL_STANDBY
管理ポリシー: AUTOMATIC
サーバー・プール: 
ディスク・グループ: DATA
マウント・ポイントのパス: 
サービス: 
タイプ: RAC
開始の同時実行性: 
停止の同時実行性: 
OSDBAグループ: dba
OSOPERグループ: oper
データベース・インスタンス: orcldr1,orcldr2
構成されたノード: dr-node1,dr-node2
データベースは管理者によって管理されています
[oracle@dr-node1 ~]$ srvctl modify database -db orcldr -role PRIMARY -startoption open
[oracle@dr-node1 ~]$ srvctl config database -db orcldr
一意のデータベース名: ORCLDR
データベース名: ORCLDR
Oracleホーム: /u01/app/oracle/product/12.1.0/dbhome_1
Oracleユーザー: oracle
spfile: +DATA/ORCLDR/PARAMETERFILE/spfileORCLDR.ora
パスワード・ファイル: +DATA/ORCLDR/PASSWORD/orapwORCLDR
ドメイン
開始オプション: open
停止オプション: immediate
データベース・ロール: PRIMARY
管理ポリシー: AUTOMATIC
サーバー・プール: 
ディスク・グループ: DATA
マウント・ポイントのパス: 
サービス: 
タイプ: RAC
開始の同時実行性: 
停止の同時実行性: 
OSDBAグループ: dba
OSOPERグループ: oper
データベース・インスタンス: orcldr1,orcldr2
構成されたノード: dr-node1,dr-node2
データベースは管理者によって管理されています

9. [新プライマリDB]DB再起動
MOUNT状態のため、DB再起動します

SQL> select instance_name,status from gv$instance;

INSTANCE_NAME                                    STATUS
------------------------------------------------ ------------------------------------
orcldr1                                          MOUNTED
orcldr2                                          MOUNTED

[oracle@dr-node1 ~]$ srvctl status database -db orcldr
インスタンスorcldr1はノードdr-node1で実行中です。
インスタンスorcldr2はノードdr-node2で実行中です。
[oracle@dr-node1 ~]$ srvctl stop database -db orcldr
[oracle@dr-node1 ~]$ srvctl status database -db orcldr
インスタンスorcldr1はノードdr-node1で実行されていません。
インスタンスorcldr2はノードdr-node2で実行されていません。
[oracle@dr-node1 ~]$ srvctl start database -db orcldr
[oracle@dr-node1 ~]$ srvctl status database -db orcldr
インスタンスorcldr1はノードdr-node1で実行中です。
インスタンスorcldr2はノードdr-node2で実行中です。

SQL> select instance_name,status from gv$instance;

INSTANCE_NAME                                    STATUS
------------------------------------------------ ------------------------------------
orcldr1                                          OPEN
orcldr2                                          OPEN

 

●[新プライマリDB]SCNを進める
しばらく新プライマリDBで運用するという想定でデータ更新します

SQL> update emp set SAL = 1111 where EMPNO = 7521;

1行が更新されました。

SQL> commit;

コミットが完了しました。
SQL> update emp set SAL = 2222 where EMPNO = 7566;

1行が更新されました。

SQL> commit;

コミットが完了しました。
SQL> update emp set SAL = 3333 where EMPNO = 7654;

1行が更新されました。

SQL> commit;

コミットが完了しました。

 

②フェイルバック(フラッシュバックDB)
旧プライマリDBをフラッシュバックDB後、スイッチオーバーでロールを入れ替えられるか検証します

【検証手順】
1. [新プライマリ]旧スタンバイDBが新プライマリDBに変換された時点のSCN取得
2. [旧プライマリ]OCRのロール、開始オプション変更
3. [旧プライマリ]DB停止
4. [旧プライマリ]MOUNTモードで起動
5. [旧プライマリ]フラッシュバック・データベース実行
6. [旧プライマリ]インスタンス1のみMOUNTモードで起動
7. [旧プライマリ]旧プライマリDBのロールをフィジカル・スタンバイに変換
8. [新プライマリ]REDO転送サービス開始
9. [新スタンバイ]DB再起動
10. [新スタンバイDB]MRP起動
11. [新プライマリDB/新スタンバイDB]スイッチオーバー

【想定】
旧プライマリDBをフラッシュバックDB後、スイッチオーバーでロールを入れ替えられること
・現プライマリDB(orcldr)がスタンバイロールになること
・現スタンバイDB(orcl)がプライマリロールになること

【検証結果】
旧プライマリDBをフラッシュバックDB後、スイッチオーバーでロールを入れ替えられた
・現プライマリDB(orcldr)がスタンバイロールになった
・現スタンバイDB(orcl)がプライマリロールになった

【作業ログ】

1. [新プライマリ]旧スタンバイDBが新プライマリDBに変換された時点のSCN取得
SQL> select to_char(standby_became_primary_scn) from v$database;

TO_CHAR(STANDBY_BECAME_PRIMARY_SCN)
------------------------------------------------------------------------------------------------------------------------
5559985

2. [旧プライマリ]OCRのロール、開始オプション変更
OCRに登録されている開始オプションとロールはプライマリ時の状態のため、手動でスタンバイ用に変更します

[oracle@node1 ~]$ srvctl config database -db orcl
一意のデータベース名: orcl
データベース名: orcl
Oracleホーム: /u01/app/oracle/product/12.1.0/dbhome_1
Oracleユーザー: oracle
spfile: +DATA/ORCL/PARAMETERFILE/spfileORCL.ora
パスワード・ファイル: +DATA/ORCL/PASSWORD/orapwORCL
ドメイン
開始オプション: open
停止オプション: immediate
データベース・ロール: PRIMARY
管理ポリシー: AUTOMATIC
サーバー・プール: 
ディスク・グループ: DATA
マウント・ポイントのパス: 
サービス: 
タイプ: RAC
開始の同時実行性: 
停止の同時実行性: 
OSDBAグループ: dba
OSOPERグループ: oper
データベース・インスタンス: orcl1,orcl2
構成されたノード: node1,node2
データベースは管理者によって管理されています
[oracle@node1 ~]$ srvctl modify database -db orcl -role PHYSICAL_STANDBY -startoption mount
[oracle@node1 ~]$ srvctl config database -db orcl
一意のデータベース名: orcl
データベース名: orcl
Oracleホーム: /u01/app/oracle/product/12.1.0/dbhome_1
Oracleユーザー: oracle
spfile: +DATA/ORCL/PARAMETERFILE/spfileORCL.ora
パスワード・ファイル: +DATA/ORCL/PASSWORD/orapwORCL
ドメイン
開始オプション: mount
停止オプション: immediate
データベース・ロール: PHYSICAL_STANDBY
管理ポリシー: AUTOMATIC
サーバー・プール: 
ディスク・グループ: DATA
マウント・ポイントのパス: 
サービス: 
タイプ: RAC
開始の同時実行性: 
停止の同時実行性: 
OSDBAグループ: dba
OSOPERグループ: oper
データベース・インスタンス: orcl1,orcl2
構成されたノード: node1,node2
データベースは管理者によって管理されています

3. [旧プライマリ]DB停止
[oracle@node1 ~]$ srvctl status database -db orcl
インスタンスorcl1はノードnode1で実行中です。
インスタンスorcl2はノードnode2で実行されていません。
[oracle@node1 ~]$ srvctl stop database -db orcl
[oracle@node1 ~]$ srvctl status database -db orcl
インスタンスorcl1はノードnode1で実行されていません。
インスタンスorcl2はノードnode2で実行されていません。

4. [旧プライマリ]MOUNTモードで起動
[oracle@node1 ~]$ srvctl status database -db orcl
インスタンスorcl1はノードnode1で実行されていません。
インスタンスorcl2はノードnode2で実行されていません。
[oracle@node1 ~]$ srvctl start database -db orcl -startoption mount
[oracle@node1 ~]$ srvctl status database -db orcl
インスタンスorcl1はノードnode1で実行中です。
インスタンスorcl2はノードnode2で実行中です。

5. [旧プライマリ]フラッシュバック・データベース実行
「1.」で取得した旧スタンバイDBが新プライマリDBに変換された時点のSCNまでDBを戻します

SQL> flashback database to scn 5559985;

フラッシュバックが完了しました。

6. [旧プライマリ]インスタンス1のみMOUNTモードで起動
インスタンスが起動している場合、後続の「7.」の「alter database convert to physical standby;」が失敗するため、インスタンス1のみMOUNTモードで起動します

[oracle@node1 ~]$ srvctl status database -db orcl
インスタンスorcl1はノードnode1で実行中です。
インスタンスorcl2はノードnode2で実行中です。
[oracle@node1 ~]$ srvctl stop instance -db orcl -instance orcl2
[oracle@node1 ~]$ srvctl status database -db orcl
インスタンスorcl1はノードnode1で実行中です。
インスタンスorcl2はノードnode2で実行されていません。

7. [旧プライマリ]旧プライマリDBのロールをフィジカル・スタンバイに変換
SQL> select db_unique_name, database_role, open_mode from v$database;

DB_UNIQUE_NAME       DATABASE_ROLE                                    OPEN_MODE
-------------------- ------------------------------------------------ ------------------------------------------------------------
orcl                 PRIMARY                                          MOUNTED

SQL> alter database convert to physical standby;

データベースが変更されました。

SQL> select instance_name,status from v$instance;

INSTANCE_NAME                                    STATUS
------------------------------------------------ ------------------------------------
orcl1                                            MOUNTED

SQL> select db_unique_name, database_role, open_mode from v$database;

DB_UNIQUE_NAME       DATABASE_ROLE                                    OPEN_MODE
-------------------- ------------------------------------------------ ------------------------------------------------------------
orcl                 PHYSICAL STANDBY                                 MOUNTED

【参考】
1つのインスタンス以外が起動しているとエラー
SQL> alter database convert to physical standby;
alter database convert to physical standby;
*
行1でエラーが発生しました。:
ORA-38777: 他のインスタンスでデータベースを起動しないでください

8. [新プライマリ]REDO転送サービス開始
SQL> select inst_id, name, value from gv$parameter where name = 'log_archive_dest_3';

INST_ID NAME                           VALUE
------- ------------------------------ --------------------------------------------------
      1 log_archive_dest_3             service=ORCL ASYNC NOAFFIRM delay=0 OPTIONAL compr
                                       ession=DISABLE max_failure=0 max_connections=1 reo
                                       pen=300 db_unique_name=ORCL net_timeout=30 valid_f
                                       or=(ONLINE_LOGFILE,PRIMARY_ROLE)

      2 log_archive_dest_3             service=ORCL ASYNC NOAFFIRM delay=0 OPTIONAL compr
                                       ession=DISABLE max_failure=0 max_connections=1 reo
                                       pen=300 db_unique_name=ORCL net_timeout=30 valid_f
                                       or=(ONLINE_LOGFILE,PRIMARY_ROLE)

SQL> select inst_id, name, value from gv$parameter where name = 'log_archive_dest_state_3';

INST_ID NAME                           VALUE
------- ------------------------------ --------------------------------------------------
      1 log_archive_dest_state_3       ENABLE
      2 log_archive_dest_state_3       ENABLE

★必要に応じて下記コマンドで有効化します
alter system set log_archive_dest_state_n = enable;

9. [新スタンバイ]DB再起動
インスタンス1しか起動していないため、DB再起動します

[oracle@node1 ~]$ srvctl status database -db orcl
インスタンスorcl1はノードnode1で実行中です。
インスタンスorcl2はノードnode2で実行されていません。
[oracle@node1 ~]$ srvctl stop database -db orcl
[oracle@node1 ~]$ srvctl status database -db orcl
インスタンスorcl1はノードnode1で実行されていません。
インスタンスorcl2はノードnode2で実行されていません。
[oracle@node1 ~]$ srvctl start database -db orcl
[oracle@node1 ~]$ srvctl status database -db orcl
インスタンスorcl1はノードnode1で実行中です。
インスタンスorcl2はノードnode2で実行中です。

10. [新スタンバイDB]MRP起動
SQL> select client_process,process,thread#,sequence#,status from v$managed_standby where process = 'MRP0';

レコードが選択されませんでした。

SQL> alter database recover managed standby database disconnect;

データベースが変更されました。

SQL> select client_process,process,thread#,sequence#,status from v$managed_standby where process = 'MRP0';

CLIENT_PROCESS       PROCESS                 THREAD#  SEQUENCE# STATUS
-------------------- -------------------- ---------- ---------- --------------------
N/A                  MRP0                          1        119 APPLYING_LOG

11. [新プライマリDB/新スタンバイDB]スイッチオーバー
スイッチオーバーでロールを入れ替えて障害発生前の状態に戻します
スイッチオーバー手順につきましては
Data Guardのスイッチオーバー/スイッチバック検証 - 忘れかけのIT備忘録をご参照ください

 

■参考資料
ロールの推移
Oracle Data Guardの使用例

記事が長くなってしまったため、フェイルオーバー後、リストア/不完全リカバリによるフェイルバックは次回書こうと思います。