東京・大阪間のAutonomous Data Guardのスイッチオーバー・フェイルオーバーにかかる時間(RTO)とデータ損失を計測してみた

#はじめに
Oracle Autonomous Database （以下ADB）には、高可用性を実現する Autonomous Data Guard （以下AuDG）という機能があります。その中でも、一つのリージョン内でスタンバイ・データベースを構成するローカルと、リージョン間で構成するクロスリージョンがあります。
今回はそれぞれの AuDG のスイッチオーバー（以下S/O）・フェイルオーバー（以下F/O）にかかる時間とその間にデータをINSERTした場合のデータ損失を計測してみました。

#構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1930162/ce4c67c6-1b79-5ba2-3f4d-49822ddc83e9.png)

#事前準備
東京リージョンにPrivate Endpointを設定したADBを作成します。今回は、Public Subnet内にアプリケーションサーバーに見立てたComputeインスタンス（以下App1）を配置し、ここからADBへ接続します。またこのComputeインスタンスから大阪リージョンのスタンバイADBへ接続するため、Remote Peering, Private DNS, Route Table, Security List, Network Security Group等を設定しておきます。

##・Remote VCN Peeringの設定
・<a href="https://qiita.com/shirok/items/90cff318816fbf2a802d" target="_blank" rel="noopener noreferrer">DRGで東京リージョンを経由して、オンプレミスと 大阪リージョンを接続してみてみた</a>
・<a href="https://qiita.com/shirok/items/192674aa6e903ea6694a" target="_blank" rel="noopener noreferrer">Oracle Cloud: リージョン間を Remote VCN Peering してみてみた</a>

##・Private DNS設定
・<a href="https://qiita.com/shirok/items/ac97cf48154c59c9a87e" target="_blank" rel="noopener noreferrer">Oracle Cloud: オンプレミスとOCIをVPN接続してPrivate DNSで名前解決してみてみた</a>
・<a href="https://qiita.com/shirok/items/4197e09dc2bfd7db82f3" target="_blank" rel="noopener noreferrer">Private DNSで PeeringしたVCNどうしホスト名(FQDN)で通信できるようにしてみてみた</a>

#ローカルAutonomous Data Guard
まずは同じVCN内にスタンバイ・データベースを構成するローカルAuDG のS/O・F/Oの計測を行います。
Public Subnetに配置したApp1にADBのWalletを配置し、接続できるか確認します。
接続できることが確認できたら、以下のSQL文を実行し、計測のために必要なシーケンスと表を作成します。

```sql
create sequence serial maxvalue 10000;
```

```sql
create table audg_test(SEQ int, time timestamp);
```

exitし、以下のシェルスクリプトを作成します。

```check.sh
#!/bin/sh

DATETAG=`date +%Y%m%d`
WORKDIR=/home/oracle/audg_checkMaintenance
LOGNAME=${WORKDIR}/log/adbdeg_${DATETAG}.log

while true
do
(

#ADBに接続し、ログファイルに追記
sqlplus -s  admin/Welcome12345#@atptokyo_tp <<! >> $LOGNAME

set echo on
set lines 200
set pages 9999
set trims on

col time for a30

insert into audg_test values(serial.nextval, localtimestamp);

select * from audg_test where time = (select max(time) from audg_test);

select instance_name, status from gv\$instance order by 1;

exit

!

sleep 1
)

done
```

このスクリプトを作成したら、早速実行します。

:::note warn
TNS_ADMINなどの環境変数が設定されていない場合ADBに接続できないので、実行前にこれらの設定を確認することをおすすめします。
:::

```
$ ./check.sh
```

実行した5秒後に、OCIのコンソール画面からS/Oを実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1930162/60603f6d-43c4-960d-da82-a721741b9221.png)

ステータスがロール変更進行中に変わります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1930162/bba56ce2-851c-8e3d-bffd-fe21d2c920eb.png)

しばらく待つと使用可能に変わりました。ローカルなので、ATPTokyoはプライマリのままです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1930162/b896466f-fdf3-db3f-dfd7-c4f8d7807127.png)

その30秒後、実行していたスクリプトを停止します。

```
$ killall -9 check.sh
```

ログを確認します。

```
1 row created.

       SEQ TIME
---------- ------------------------------
	 1 28-OCT-21 04.56.13.747712 AM

INSTANCE_NAME	 STATUS
---------------- ------------
euk1pod2	 OPEN

1 row created.

       SEQ TIME
---------- ------------------------------
	 2 28-OCT-21 04.56.15.045479 AM

INSTANCE_NAME	 STATUS
---------------- ------------
euk1pod2	 OPEN

1 row created.

       SEQ TIME
---------- ------------------------------
	 3 28-OCT-21 04.56.16.279443 AM

INSTANCE_NAME	 STATUS
---------------- ------------
euk1pod2	 OPEN
```

このように1秒毎にデータがINSERTされているのがわかります。
S/Oの前後はこのようになっています。

```
1 row created.

       SEQ TIME
---------- ------------------------------
	15 28-OCT-21 04.56.31.587429 AM

INSTANCE_NAME	 STATUS
---------------- ------------
euk1pod2	 OPEN

ERROR:
ORA-12514: TNS:listener does not currently know of service requested in connect
descriptor


ERROR:
ORA-12162: TNS:net service name is incorrectly specified


SP2-0306: Invalid option.
Usage: CONN[ECT] [{logon|/|proxy} [AS {SYSDBA|SYSOPER|SYSASM|SYSBACKUP|SYSDG|SYSKM|SYSRAC}] [edition=value]]
where <logon> ::= <username>[/<password>][@<connect_identifier>]
      <proxy> ::= <proxyuser>[<username>][/<password>][@<connect_identifier>]
SP2-0157: unable to CONNECT to ORACLE after 3 attempts, exiting SQL*Plus

1 row created.

       SEQ TIME
---------- ------------------------------
	21 28-OCT-21 04.57.38.143087 AM

INSTANCE_NAME	 STATUS
---------------- ------------
em31pod3	 OPEN
```

約1分間ADBへの接続に失敗し、S/O完了後はINSTANCE_NAMEが変わっていることがわかります。

:::note info
INSTANCE_NAMEがeuk1podからem31podに変わった理由について、東京リージョンには2021年11月現在可用性ドメインが1つしかないため、ローカルでAuDGを構成した場合、2台の異なるExadataの筐体間にプライマリ・スタンバイが作成され冗長性が組まれています。
ADBは大半のケースでExadataのFULLラック上で構成されており、それぞれeuk1podやem31podがデータベース名で、8ノードRACで構成されています。上記はeuk1podというデータベースからem31podという異なるExadata筐体上で稼働しているデータベースにスイッチオーバーしたということになります。なお、euk1pod1, euk1pod2, といった形で末尾に振られているのはインスタンス番号になります。FULLラックは8台のDBサーバで構成されておりますので、1から8までの数字が付与されています。
:::

ログから得られた時系列グラフを以下に示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1930162/771182d4-3318-6f2c-edaa-83b8fdc90c62.png)

S/Oには95秒かかり、INSERTは70秒間失敗しました。

とはいえ、実際の運用ではS/Oの実行中にADBへ接続し、何らかの処理を行うことはほぼないと思います。
しかしF/Oに関しては、実際の運用でも何らかの処理を行っている途中に自動F/Oが実行されることも考えられます。

ということで先ほどの処理をF/Oの実行中にやってみます。
S/Oと異なる点は、**手動F/Oは平常時にコンソールからは実行できない**ということです。
プライマリ・データベースに障害が発生したかアクセスできず、自動F/Oの条件が満たされていない場合、OCIコンソールには、自動F/Oが成功しなかったことを示すバナーが表示され、データ損失の可能性などの理由が示され、手動F/Oを開始するためのリンクが提供されます。
検証などの目的で、意図的に手動F/Oを行いたい場合はOCI CLIを使用します。

:::note info
自動F/OはローカルAuDGでのみ有効になっています。
クロスリージョンAuDGでは無効で、手動F/Oしかできません。
:::

手動F/Oについては、<a href="https://qiita.com/wahagon/items/040bf6b5a90da40b4ac0" target="_blank" rel="noopener noreferrer">Autonomous Data Guardで東京、大阪リージョン間のフェイルオーバーをやってみた</a> も参考にしてください。

S/Oと同様に、スクリプト実行から5秒後にF/Oを行い、コンソール上のプライマリADBが使用可能になった30秒後にプロセスをkillしました。

ログから得られた時系列グラフを以下に示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1930162/e52b53b2-b583-2a69-c7fa-569721a946d1.png)

F/Oには135秒かかり、INSERTは95秒間失敗しました。
ドキュメントでは、ローカルのAuDGのRTOおよびRPOは以下のようになっています。

- **自動フェイルオーバー**：RTOは2分、RPOはゼロ
- **手動フェイルオーバー**：RTOは2分、RPOは最大5分

このうち、手動F/OのRTOがドキュメント通り2分前後であることが確認できました。
**なお、ローカルに関してはS/O・F/Oの前後でADBへの接続のための設定変更などは行う必要はありません。**

#クロスリージョンAutonomous Data Guard
次に、大阪リージョンにスタンバイ・データベースを構成するクロスリージョンAuDGでS/O・F/Oの検証を行います。
リモートVCNピアリング・プライベートDNSの設定ができたら、スタンバイ・データベースの情報が記載されたWalletをダウンロードし直します。
クロスリージョンAuDGが有効化された後にダウンロードすると、tnsnames.oraは以下のようになっているはずです。

```tnsnames.ora（接続サービスtpのみ抜粋）
atptokyo_tp = (description_list= (failover=on) (load_balance=off) 
   (description= (retry_count=15)(retry_delay=3)(address=(protocol=tcps)(port=1522)(host=clotrwte.adb.ap-tokyo-1.oraclecloud.com))(connect_data=(service_name=sya6vphk3pzlkhq_atptokyo_tp.adb.oraclecloud.com))(security=(ssl_server_cert_dn="CN=adb.ap-tokyo-1.oraclecloud.com, OU=Oracle ADB TOKYO, O=Oracle Corporation, L=Redwood City, ST=California, C=US"))) 
   (description= (retry_count=15)(retry_delay=3)(address=(protocol=tcps)(port=1522)(host=kclskqsl.adb.ap-osaka-1.oraclecloud.com))(connect_data=(service_name=sya6vphk3pzlkhq_atptokyo_tp.adb.oraclecloud.com))(security=(ssl_server_cert_dn="CN=adb.ap-osaka-1.oraclecloud.com, OU=Oracle ADB OSAKA, O=Oracle Corporation, L=Redwood City, ST=California, C=US"))))
```

F/Oが行われると、下の大阪のADBに接続するよう記述されています。

S/Oを行う前に、先ほど使用したスクリプトを少し修正します。

```check2.sh
#!/bin/sh

DATETAG=`date +%Y%m%d`
WORKDIR=/home/oracle/audg_checkMaintenance
LOGNAME=${WORKDIR}/log/adbdeg_${DATETAG}.log

while true
do
(

#ADBに接続し、ログファイルに追記
sqlplus -s  admin/Welcome12345#@atptokyo_tp <<! >> $LOGNAME

set echo on
set lines 200
set pages 9999
set trims on

col time for a30

insert into audg_test values(serial.nextval, localtimestamp);

select * from audg_test where time = (select max(time) from audg_test);

select instance_name, status from gv\$instance order by 1;

select cloud_identity from v\$pdbs;

exit

!

sleep 1

)

done

!
```

接続先ADBのregionが切り替わったことを確認するため、1行追加し、ローカルと同じ手順でS/Oを行います。

出力されたログには以下のようにregionの情報も表示されています。

```
1 row created.

       SEQ TIME
---------- ------------------------------
	 1 08-NOV-21 02.27.38.315956 PM

INSTANCE_NAME	 STATUS
---------------- ------------
euk1pod2	 OPEN

CLOUD_IDENTITY
----------------------------------
{
  "DATABASE_NAME" : "ATPTOKYO",
  "REGION" : "ap-tokyo-1",
  "TENANT_OCID" : （省略）,
  "DATABASE_OCID" : （省略）,
  "COMPARTMENT_OCID" : （省略）,
  "OUTBOUND_IP_ADDRESS" :[158.101.128.153],
  "AUTOSCALABLE_STORAGE" : false,
  "BASE_SIZE" : 1099511627776,
  "INFRASTRUCTURE" : null,
  "SERVICE" : null,
  "APPLICATIONS" :[]
}
```

S/O完了後のログは以下のようになっています。

```
1 row created.

       SEQ TIME
---------- ------------------------------
	61 08-NOV-21 02.33.18.524043 PM

INSTANCE_NAME	 STATUS
---------------- ------------
ev11pod2	 OPEN

CLOUD_IDENTITY
----------------------------------
{
  "DATABASE_NAME" : "ATPTOKYO",
  "REGION" : "ap-osaka-1",
  "TENANT_OCID" : （省略）,
  "DATABASE_OCID" : （省略）,
  "COMPARTMENT_OCID" : （省略）,
  "OUTBOUND_IP_ADDRESS" :[168.138.32.254],
  "AUTOSCALABLE_STORAGE" : false,
  "BASE_SIZE" : 1099511627776,
  "INFRASTRUCTURE" : null,
  "SERVICE" : null,
  "APPLICATIONS" :[]
}
```

以上より、REGIONがtokyoからosakaに切り替わったことがわかりました。
ログの結果から時系列グラフは以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1930162/c50023bc-4abb-5e70-9cfe-9e889684a655.png)

S/Oでリージョンが切り替わった後は、**ローカルと同様に自動で接続先が切り替わります**が、切り替わった後の大阪ADBへの接続に45秒かかっていました。これは接続に使用するtnsnames.oraの記述の順番に起因します。先ほどのtnsnames.oraには、東京リージョンの接続情報の下に大阪リージョンの接続情報が記載されていました。tnsnames.oraは上から読み取られていくため、大阪ADBにすぐに接続したい場合は、マニュアルにも推奨されているようにWalletファイルをダウンロードし直すか、順番を入れ替える必要があります。

続いてF/Oも検証してみました。
ログから得られた時系列グラフは以下です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1930162/73cb1568-6c43-ff7d-9d84-925c612cf431.png)

ドキュメントでは、クロスリージョンのAuDGのRTOおよびRPOは以下のようになっています。

- **自動フェイルオーバー**：使用不可
- **手動フェイルオーバー**：RTOは1時間、RPOは最大5分

手動F/Oにかかる基本的には更新データ量に依存しますが、今回の手動F/Oにおいて利用できない時間は約5分でした。
なお、データ量が同じでもF/Oにかかる時間は多少のバラつきがありました。

#さいごに
今回の検証で、ローカル・クロスリージョン Autonomous Data GuardのSwitchOver・FailOverにかかる時間と、その間に発生したデータ損失を確認できました。
なお検証や動作確認のときはよくやってしまうと思うのですが、ローカルでもクロスリージョンでも、S/O・F/Oを実行した後すぐに再度S/O・F/Oを行ってしまうと、ADBが「使用不可」になってしまう場合が稀にあるので、一度S/O・F/Oを実行した後はある程度（10分くらい）時間を置くことをおすすめします。
サイト障害や広域障害の対策として、コンソール上でクリック数回で構成できる上、復旧も素早くできる便利な機能ですので、ぜひ活用してみてください。


#参考
- <a href="https://docs.oracle.com/en-us/iaas/tools/oci-cli/3.0.5/oci_cli_docs/cmdref/db/autonomous-database/fail-over.html" target="_blank" rel="noopener noreferrer">OCI CLI コマンドリファレンス</a>

- <a href="https://docs.oracle.com/ja-jp/iaas/adbdataguard/autonomous-data-guard-about.html#GUID-045AD017-8120-4BDC-AF58-7430FFE28D2B" target="_blank" rel="noopener noreferrer">障害時リカバリでのAutonomous Databaseでのスタンバイ・データベースの使用</a>

- <a href="https://docs.oracle.com/ja-jp/iaas/adbdataguard/autonomous-data-guard-failover.html" target="_blank" rel="noopener noreferrer">スタンバイ・データベースとの手動フェイルオーバー</a>