Data Guard アーカイブギャップを検証する（Oracle Database 19c）

# アーカイブギャップとは？
　Data Guard はプライマリ・データベースに対する更新情報（REDO）をスタンバイ・データベースに転送し、スタンバイ・データベースに適用することで複数のデータベースのデータを同期するテクノロジーです。REDO の転送方法はトランザクションの単位（リアルタイム適用）またはアーカイブログの単位（アーカイブログ適用）ですが、最近はほとんどの場合リアルタイム適用が採用されています。しかしプライマリ・データベースとスタンバイ・データベースの差分が大きくなった場合はアーカイブログの単位で差が発生します。これをアーカイブギャップと呼び、V\\$ARCHIVE_GAP ビューで確認できます。本記事ではいくつかの状況で V\\$ARCHIVE_GAP ビューがどのように変化するかを確認します。

[V$ARCHIVE_GAP ビュー](https://docs.oracle.com/cd/F19136_01/refrn/V-ARCHIVE_GAP.html#GUID-6E28C3F2-F517-4F55-B93E-7CF02E24CFC3) は以下の列構成になっています。

|列名|データ型|説明|備考
|:---|:---|:---|:---|
|THREAD#|NUMBER|欠落しているアーカイブREDOのスレッド番号|シングル環境では1|
|LOW_SEQUENCE#|NUMBER|スタンバイ・システムで受信済の最小順序番号||
|HIGH_SEQUENCE#|NUMBER|スタンバイ・システムで受信済の最大順序番号||
|CON_ID|NUMBER|コンテナID||
 
　プライマリ・データベースとスタンバイ・データベースが同期している状態の場合、V\\$ARCHIVE_GAP ビューにはレコードは確認できません。

 ```SQL: V$ARCHIVE_GAP ビューの確認
SQL> SELECT * FROM V$ARCHIVE_GAP;

レコードが選択されませんでした。
 ```
 
# アーカイブギャップの検証
　アーカイブギャップを発生させて、V$ARCHIVE_GAP ビューの状態を確認します。
 本記事ではプライマリ・データベース（db_unique_name）を O19P、スタンバイ・データベースを O19S としています。

## 管理スタンバイの停止
 スタンバイ・データベースで ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL 文を実行し、管理スタンバイを停止します。これによりアーカイブログの受信は継続されますが、適用は行われません。
 
 その後、プライマリ・データベースでログスイッチを複数回実行します。

 ```SQL: スタンバイで管理スタンバイの停止
SQL> SELECT status FROM V$MANAGED_STANDBY WHERE process LIKE 'MRP%';

STATUS
------------
APPLYING_LOG

SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;

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

プライマリ・データベースでアーカイブログの状況を V\\$ARCHIVED_LOG ビューで確認します。シーケンス番号 114 以降がスタンバイ・データベースで適用されていない（APPLIED=NO）ことがわかります。

```SQL: ログスイッチ後のアーカイブ状況（プライマリ）
SQL> SELECT name, sequence#, archived, applied FROM V$ARCHIVED_LOG ORDER BY sequence#;

NAME                                                          SEQUENCE# ARC APPLIED
------------------------------------------------------------ ---------- --- ---------
...
/u01/app/oracle/admin/O19P/archive/1_113_1092062913.dbf             113 YES NO
O19S                                                                113 YES YES
/u01/app/oracle/admin/O19P/archive/1_114_1092062913.dbf             114 YES NO
O19S                                                                114 YES NO
/u01/app/oracle/admin/O19P/archive/1_115_1092062913.dbf             115 YES NO
O19S                                                                115 YES NO
/u01/app/oracle/admin/O19P/archive/1_116_1092062913.dbf             116 YES NO
O19S                                                                116 YES NO
/u01/app/oracle/admin/O19P/archive/1_117_1092062913.dbf             117 YES NO
O19S                                                                117 YES NO

28行が選択されました。
```

この状況でアーカイブ・ギャップを確認してもレコードは検出されません。適用されていないアーカイブ・ログが存在しても「アーカイブギャップ」とはみなされないことがわまります。

```SQL:アーカイブギャップの確認
SQL> SELECT * FROM V$ARCHIVE_GAP;

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

## スタンバイ・インスタンス停止
　スタンバイ・インスタンスを停止した状態で複数のログスイッチを行い、アーカイブの差分を発生させます。

```SQL:スタンバイ・データベースの停止
SQL> SELECT status FROM V$MANAGED_STANDBY WHERE process LIKE 'MRP%';

STATUS
------------
APPLYING_LOG

SQL> SHUTDOWN IMMEDIATE
ORA-01109: データベースがオープンされていません。

データベースがディスマウントされました。
ORACLEインスタンスがシャットダウンされました。
```

アーカイブログの状況を確認すると、シーケンス番号 118 以降のアーカイブログがスタンバイ・データベース（O19S）へ転送されていないことがわかります。


```SQL: SQL: ログスイッチ後のアーカイブ状況（プライマリ）
SQL> SELECT name, sequence#, archived, applied FROM V$ARCHIVED_LOG ORDER BY sequence#;

NAME                                                          SEQUENCE# ARC APPLIED
------------------------------------------------------------ ---------- --- ---------
...
/u01/app/oracle/admin/O19P/archive/1_117_1092062913.dbf             117 YES NO
O19S                                                                117 YES NO
/u01/app/oracle/admin/O19P/archive/1_118_1092062913.dbf             118 YES NO
/u01/app/oracle/admin/O19P/archive/1_119_1092062913.dbf             119 YES NO
/u01/app/oracle/admin/O19P/archive/1_120_1092062913.dbf             120 YES NO
/u01/app/oracle/admin/O19P/archive/1_121_1092062913.dbf             121 YES NO

28行が選択されました。
```

 この状況でプライマリ・データベースでアーカイブ・ギャップを確認してもレコードは検出されません。スタンバイ・データベースが起動していない状況でアーカイブ・ログが存在しても V$ARCHIVE_GAP ビューでは検出できないことがわかります。 

```SQL:アーカイブギャップの確認
SQL> SELECT * FROM V$ARCHIVE_GAP;

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

## アーカイブ処理を停止
　スタンバイ・インスタンスへの REDO 転送を停止し、アーカイブの差分を発生させます。初期化パラメーター log_archive_dest_state_N を defer に設定することで REDO 転送を停止します。

 ```SQL: REDO転送の停止
SQL> SHOW parameter log_archive_dest_2

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
log_archive_dest_2                   string      SERVICE=O19S ASYNC VALID_FOR=(
                                                 online_logfiles, primary_role)
                                                  db_unique_name=O19S
...
SQL>  ALTER SYSTEM SET log_archive_dest_state_2 = defer;

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

 　プライマリ・データベースの複数回ログスイッチを発生させ、アーカイブ差分を発生させます。シーケンス番号 123 以降がスタンバイに転送されていません。この状況でアーカイブ・ギャップを確認してもレコードは検出されません。

```SQL: アーカイブログの確認
SQL> SELECT name, sequence#, archived, applied FROM V$ARCHIVED_LOG ORDER BY sequence#;

NAME                                                          SEQUENCE# ARC APPLIED
------------------------------------------------------------ ---------- --- ---------
...
/u01/app/oracle/admin/O19P/archive/1_122_1092062913.dbf             122 YES NO
O19S                                                                122 YES NO
/u01/app/oracle/admin/O19P/archive/1_123_1092062913.dbf             123 YES NO
/u01/app/oracle/admin/O19P/archive/1_124_1092062913.dbf             124 YES NO
/u01/app/oracle/admin/O19P/archive/1_125_1092062913.dbf             125 YES NO
/u01/app/oracle/admin/O19P/archive/1_126_1092062913.dbf             126 YES NO

34行が選択されました。
```

```SQL: アーカイブギャップの確認
SQL> SELECT * FROM V$ARCHIVE_GAP;

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

##  アーカイブの削除
スタンバイ・データベースを停止し、プライマリ・データベースを更新することでアーカイブ差分を発生させます。その後、送信予定のアーカイブログを物理的に削除し、アーカイブギャップを確認します。

```SQL: アーカイブギャップの発生
SQL> SELECT name, sequence#, archived, applied FROM V$ARCHIVED_LOG ORDER BY sequence#;

NAME                                                          SEQUENCE# ARC APPLIED
------------------------------------------------------------ ---------- --- ---------
...
/u01/app/oracle/admin/O19P/archive/1_129_1092062913.dbf             129 YES NO
O19P                                                                129 YES NO
/u01/app/oracle/admin/O19P/archive/1_130_1092062913.dbf             130 YES NO
/u01/app/oracle/admin/O19P/archive/1_131_1092062913.dbf             131 YES NO
/u01/app/oracle/admin/O19P/archive/1_132_1092062913.dbf             132 YES NO
/u01/app/oracle/admin/O19P/archive/1_133_1092062913.dbf             133 YES NO
/u01/app/oracle/admin/O19P/archive/1_134_1092062913.dbf             134 YES NO

49行が選択されました。
```

上記の例ではシーケンス番号 130 番移行のアーカイブログがスタンバイ・データベースに転送できていません。シーケンス番号 130 のアーカイブログを削除してからスタンバイ・データベースを起動します。プライマリ・データベースは差分となるアーカイブログ（シーケンス番号 130）をスタンバイ・データベースに送信しようとしますが、ファイルが存在しないのでエラーが発生します。アラートログに以下のメッセージが出力されます。

```shell: プライマリ・データベースのアラートログ出力
2024-02-12T17:07:47.312991+09:00
Errors in file /u01/app/oracle/diag/rdbms/o19p/O19P/trace/O19P_tt00_7930.trc:
ORA-00308: cannot open archived log '/u01/app/oracle/admin/O19P/archive/1_130_1092062913.dbf'
ORA-27037: unable to obtain file status
Linux-x86_64 Error: 2: No such file or directory
Additional information: 7
```

スタンバイ・データベースでアーカイブ・ギャップを確認すると、シーケンス番号 130 が確認できます。

```SQL: アーカイブギャップの確認
SQL> SELECT * FROM V$ARCHIVE_GAP;

   THREAD# LOW_SEQUENCE# HIGH_SEQUENCE#     CON_ID
---------- ------------- -------------- ----------
         1           130            130          1
```

V$ARCHIVE_GAP の[マニュアル](https://docs.oracle.com/cd/F19136_01/refrn/V-ARCHIVE_GAP.html#GUID-6E28C3F2-F517-4F55-B93E-7CF02E24CFC3)には以下のように記載されています。

> マニュアルの記載
> V$ARCHIVE_GAPは、スタンバイ・データベースのアーカイブ・ギャップに関する情報を示します。このビューを使用すると、現行のリカバリ・インカーネーションに対してリカバリを阻止している現行のアーカイブ・ギャップを確認できます。


このためV\\$ARCHIVE_GAP ビューは、転送するアーカイブログが存在しない場合や、アーカイブログ情報保存期間（初期化パラメーター control_file_record_keep_time）を過ぎて V\\$ARCHIVED_LOG ビューにアーカイブログの情報が存在しない等の理由でエラーが発生した場合にのみ有効な情報が得られることがわかります。

Author: Noriyoshi Shinoda / Date: February 12, 2024