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はインストールされないため、個別でインストールが必要です
■検証環境、前提、設定情報
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)のロールがプライマリロールになった
【作業ログ】
フェイルバックはフラッシュバック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)がプライマリロールになった
【作業ログ】
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の使用例
記事が長くなってしまったため、フェイルオーバー後、リストア/不完全リカバリによるフェイルバックは次回書こうと思います。