Data Guardのスナップショット・スタンバイについて、机上の知識はあるものの、実務経験が無いため、実際の動きを検証しました。
スナップショット・スタンバイ(スナップショット・スタンバイ・データベース)は一時的にプライマリDBと同期解除された更新可能なスタンバイDBです。
フィジカル・スタンバイ(フィジカル・スタンバイ・データベース)の場合、スタンバイDBはMOUNTモードのため、問い合わせや更新はできません。(Oracle Active Data Guardライセンスを購入すればスタンバイDBもリアルタイム問合せできますが、本検証では対象外です)
フィジカル・スタンバイと同様、プライマリDBからREDOデータを受信・アーカイブしますが、適用はしません。(プライマリDBとスタンバイDBで同期されなくなるため差分が出ますが、REDOデータを受信・アーカイブするためプライマリDBのデータ保護は可能になっています)
スナップショット・スタンバイはプライマリDBからスタンバイDBを切り離してスタンバイDBに対して更新することができるため、主に本番同等のデータでテスト目的で使用されることが多いようです。
スナップショット・スタンバイがフィジカル・スタンバイに戻るタイミングでスナップショット・スタンバイの更新が破棄され、プライマリDBから受信したREDOデータが適用されます。(スナップショット・スタンバイへ変換される直前の状態に戻ります)
スナップショット・スタンバイの変換にはいくつか制約があります。(ドキュメントID 1740162.1)
・フィジカル・スタンバイ・データベースであること
・プライマリDB、スタンバイDBともに高速リカバリ領域(DB_RECOVER_FILE_DEST、DB_RECOVER_FILE_DEST_SIZE)が設定されていること
・スタンバイDBのlog_archive_dest_nパラメータでvalid_forを指定している場合、下記の組み合わせのいずれかが含まれていること
- online_logfile, standby_role
- all_logfile, standby_role
- all_logfile, all_roles
※想定ですが、スタンバイDB(スタンバイ・ロール)がトランザクションの更新情報(オンラインREDOログデータ)を出力するための設定が必要なのだと思います
■検証環境
NSA (Network Server Async)
プライマリDBのREDOデータを非同期でスタンバイDBのRFSプロセスへ転送するプロセス
転送後、RFSプロセスからの応答は待たない
※NSAプロセスに対してNSSプロセスというスタンバイDBと同期を取りながらREDO転送するプロセスもありますが、詳細は後日検証予定の保護モードで解説しようと思います
RFS (Remote File Server)
プライマリDBから転送されてきたREDOデータを受信後、スタンバイREDOログファイルに書き込むプロセス
MRP (Management Recovery Process)
管理リカバリプロセス
スタンバイ・REDOログファイルやアーカイブログのREDOデータをデータファイルに適用するプロセス
RACの場合、いずれかのノードに存在します
【補足】
通常、REDOデータを受信・適用する場合、スタンバイDBにスタンバイ・REDOログファイルがあれば十分ですが、スナップショット・スタンバイの場合、更新情報をオンライン・REDOログファイルに書き込むため、オンライン・REDOログが必要です
スイッチオーバーやフェイルオーバーしたときもオンライン・REDOログファイルが必要です
■前提
・プライマリDB・スタンバイDBともに2ノードRAC(管理者管理型DB)
・スタンバイDBはフィジカル・スタンバイ
・保護モードは最大パフォーマンスモード
・Data Guard Broker構成なし
■設定情報
SQL> --ロール
SQL> select db_unique_name, database_role from v$database;
DB_UNIQUE_NAME DATABASE_ROLE
-------------------- ------------------------------------------------
orcl PRIMARY
SQL> --適用モード(リアルタイム適用)
SQL> select dest_name, recovery_mode from v$archive_dest_status where type = 'PHYSICAL';
DEST_NAME RECOVERY_MODE
------------------------------ ------------------------------
LOG_ARCHIVE_DEST_3 MANAGED REAL TIME APPLY
SQL> --スイッチオーバー可否
SQL> select switchover_status from v$database;
SWITCHOVER_STATUS
------------------------------------------------------------
TO STANDBY
SQL> --保護モード
SQL> select protection_mode, protection_level from v$database;
PROTECTION_MODE PROTECTION_LEVEL
------------------------------ ------------------------------
MAXIMUM PERFORMANCE MAXIMUM PERFORMANCE
スタンバイDB
SQL> --ロール
SQL> select db_unique_name, database_role from v$database;
DB_UNIQUE_NAME DATABASE_ROLE
-------------------- ------------------------------------------------
orcldr PHYSICAL STANDBY
SQL> --管理リカバリモード
SQL> select client_process, process, thread#, sequence#, status from v$managed_standby where process like 'MRP%';
CLIENT_PROCESS PROCESS THREAD# SEQUENCE# STATUS
-------------------- -------------------- ---------- ---------- --------------------
N/A MRP0 1 56 APPLYING_LOG
SQL> --スタンバイ・REDOログファイル
SQL> select group#, thread#, sequence#, archived, status from v$standby_log order by group#, thread#;
GROUP# THREAD# SEQUENCE# ARCHIVED STATUS
---------- ---------- ---------- --------- --------------------
5 1 0 NO UNASSIGNED
6 1 0 NO UNASSIGNED
7 1 56 YES ACTIVE
8 2 0 NO UNASSIGNED
9 2 0 NO UNASSIGNED
10 2 47 YES ACTIVE
■検証パターン
①スナップショット・スタンバイへ変換(切り離し)
②プライマリDB、スタンバイDBでそれぞれデータ更新
③フィジカル・スタンバイへ変換(切り戻し)
■検証
①スナップショット・スタンバイへ変換(切り離し)
フィジカル・スタンバイからスナップショット・スタンバイへ変換できるか検証します
【検証手順】
1. [スタンバイDB]MRP停止
2. [スタンバイDB]起動モード確認
3. [スタンバイDB]高速リカバリ領域確認
4. [スタンバイDB]スナップショット・スタンバイへ変換
5. [スタンバイDB]スタンバイDBを読み書きモードでオープン
【想定】
フィジカル・スタンバイからスナップショット・スタンバイへ変換できること
【検証結果】
フィジカル・スタンバイからスナップショット・スタンバイへ変換できた
【作業ログ】
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 56 APPLYING_LOG
SQL> alter database recover managed standby database cancel;
データベースが変更されました。
SQL> select client_process, process, thread# ,sequence# ,status from v$managed_standby where process = 'MRP0';
レコードが選択されませんでした。
2. [スタンバイDB]起動モード確認
SQL> select instance_name, status from gv$instance;
INSTANCE_NAME STATUS
------------------------------ --------------------
orcldr1 MOUNTED
orcldr2 MOUNTED
★MOUNTモードになっていればOK
3. [スタンバイDB]高速リカバリ領域確認
内部でフラッシュバック・データベースを使いますが、明示的にフラッシュバック・ログを設定する必要はありません
SQL> select INST_ID,NAME,VALUE from gv$parameter where name='db_recovery_file_dest' order by INST_ID;
INST_ID NAME VALUE
------- ---------------------------------------- --------------------------------------------------
1 db_recovery_file_dest +FRA
2 db_recovery_file_dest +FRA
SQL> select INST_ID,NAME,VALUE from gv$parameter where name='db_recovery_file_dest_size' order by INST_ID;
INST_ID NAME VALUE
------- ---------------------------------------- --------------------------------------------------
1 db_recovery_file_dest_size 5017436160
2 db_recovery_file_dest_size 5017436160
4. [スタンバイDB]スナップショット・スタンバイへ変換
SQL> select DATABASE_ROLE from v$database;
DATABASE_ROLE
------------------------------------------------
PHYSICAL STANDBY
SQL> alter database convert to snapshot standby;
データベースが変更されました。
SQL> select DATABASE_ROLE from v$database;
DATABASE_ROLE
------------------------------------------------
SNAPSHOT STANDBY
5. [スタンバイDB]スタンバイDBを読み書きモードでオープン
SQL> select instance_name, status from gv$instance;
INSTANCE_NAME STATUS
------------------------------ --------------------
orcldr1 MOUNTED
orcldr2 MOUNTED
★MOUNTモードのままのため、DB再起動
[oracle@dr-node1 ~]$ srvctl status database -db orcldr
srvctl stop 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 -startoption "read write"
[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
★OPENモード(更新可能状態)になった
②プライマリDB、スタンバイDBでそれぞれデータ更新
プライマリDB、スタンバイDBでそれぞれデータを更新して下記を検証します
・プライマリDBへの更新がスタンバイDBへ反映されていないこと
・スタンバイDBへの更新がプライマリDBへ反映されていないこと
【検証手順】
1. [プライマリDB]データ更新
2. [スタンバイDB]プライマリDBの更新データ確認
3. [スタンバイDB]データ更新
4. [プライマリDB]スタンバイDBの更新データ確認
【想定】
・プライマリDBへの更新がスタンバイDBへ反映されていないこと
・スタンバイDBへの更新がプライマリDBへ反映されていないこと
【検証結果】
・プライマリDBへの更新がスタンバイDBへ反映されていなかった
・スタンバイDBへの更新がプライマリDBへ反映されていなかった
【作業ログ】
SQL> select * from emp where EMPNO in(7369, 7499);
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- ---------- ---------- -------- ---------- ---------- ----------
7369 SMITH CLERK 7902 80-12-17 800 20
7499 ALLEN SALESMAN 7698 81-02-20 1600 300 30
SQL> update emp set SAL = 9999 where EMPNO = 7369;
1行が更新されました。
SQL> commit;
コミットが完了しました。
SQL> select * from emp where EMPNO in(7369, 7499);
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- ---------- ---------- -------- ---------- ---------- ----------
7369 SMITH CLERK 7902 80-12-17 9999 20
7499 ALLEN SALESMAN 7698 81-02-20 1600 300 30
2. [スタンバイDB]プライマリDBの更新データ確認
SQL> select * from emp where EMPNO in(7369, 7499);
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- ---------- ---------- -------- ---------- ---------- ----------
7369 SMITH CLERK 7902 80-12-17 800 20
7499 ALLEN SALESMAN 7698 81-02-20 1600 300 30
★スタンバイDBのEMPNO7369のSALは更新されていなかった
3. [スタンバイDB]データ更新
SQL> select * from emp where EMPNO in(7369, 7499);
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- ---------- ---------- -------- ---------- ---------- ----------
7369 SMITH CLERK 7902 80-12-17 800 20
7499 ALLEN SALESMAN 7698 81-02-20 1600 300 30
SQL> update emp set SAL = 9999 where EMPNO = 7499;
1行が更新されました。
SQL> commit;
コミットが完了しました。
SQL> select * from emp where EMPNO in(7369, 7499);
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- ---------- ---------- -------- ---------- ---------- ----------
7369 SMITH CLERK 7902 80-12-17 800 20
7499 ALLEN SALESMAN 7698 81-02-20 9999 300 30
4. [プライマリDB]スタンバイDBの更新データ確認
SQL> select * from emp where EMPNO in(7369, 7499);
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- ---------- ---------- -------- ---------- ---------- ----------
7369 SMITH CLERK 7902 80-12-17 9999 20
7499 ALLEN SALESMAN 7698 81-02-20 1600 300 30
★プライマリDBのEMPNO7499のSALは更新されていなかった
③フィジカル・スタンバイへ変換(切り戻し)
スナップショット・スタンバイからフィジカル・スタンバイへ変換できるか検証します
【検証手順】
1. [スタンバイDB]DB停止
2. [スタンバイDB]インスタンス1をMOUNTモード起動
3. [スタンバイDB]起動モード確認
4. [スタンバイDB]フィジカル・スタンバイへ変換
5. [スタンバイDB]DB再起動
6. [スタンバイDB]MRP起動
【想定】
スナップショット・スタンバイからフィジカル・スタンバイへ変換できること
【検証結果】
スナップショット・スタンバイからフィジカル・スタンバイへ変換できた
【作業ログ】
[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で実行されていません。
2. [スタンバイDB]インスタンス1をMOUNTモード起動
RACの場合、1つのインスタンス以外はすべて停止した状態にします
[oracle@dr-node1 ~]$ srvctl status database -db orcldr
インスタンスorcldr1はノードdr-node1で実行されていません。
インスタンスorcldr2はノードdr-node2で実行されていません。
[oracle@dr-node1 ~]$ srvctl start instance -db orcldr -node dr-node1
[oracle@dr-node1 ~]$ srvctl status database -db orcldr
インスタンスorcldr1はノードdr-node1で実行中です。
インスタンスorcldr2はノードdr-node2で実行されていません。
3. [スタンバイDB]起動モード確認
SQL> select instance_name, status from gv$instance;
INSTANCE_NAME STATUS
------------------------------------------------ ------------------------------------
orcldr1 MOUNTED
★MOUNTモードになっていればOK
4. [スタンバイDB]フィジカル・スタンバイへ変換
SQL> select DATABASE_ROLE from v$database;
DATABASE_ROLE
------------------------------------------------
SNAPSHOT STANDBY
sql> alter database convert to physical standby;
データベースが変更されました。
SQL> select DATABASE_ROLE from v$database;
DATABASE_ROLE
------------------------------------------------
PHYSICAL STANDBY
5. [スタンバイDB]DB再起動
[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
------------------------------------------------ ------------------------------------
orcldr2 MOUNTED
orcldr1 MOUNTED
6. [スタンバイ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 2 53 APPLYING_LOG
★REDO適用モードに戻った
■参考文献
フィジカルおよびスナップショット・スタンバイ・データベースの管理
■おわりに
ログは割愛しますが、スナップショット・スタンバイ変換中もスタンバイDBのv$archived_logにはプライマリDBから受信したアーカイブログが登録され、APPLIEDはNOのままであることも確認できました。