OCI DBCS VM で Data Guard を有効化して、ロールベース・サービスを構成して PRIMARYロール に透過的に接続してみる。(Oracle Cloud Infrastructure)

Oracle Cloud Infrastructure(以下、OCI) の DBCS(VM) で Data Guard を有効化して、
ロールベース・サービスを構成して PRIMARYロール の DB に透過的に接続してみるやで。
彡(^)(^)

# 1. Data Guard の有効化 in OCI DBCS VM

OCI DBCS VM の Data Guard有効化 は マニュアル や下記記事の通りです。
基本Webコンソールでポチポチするだけ彡(ﾟ)(ﾟ)

> 仮想マシンDBシステムでOracle Data Guardを有効にするには
> https://docs.oracle.com/ja-jp/iaas/Content/Database/Tasks/usingdataguard.htm
> ：
> 6. 「Data Guardアソシエーション」セクションで、「Data Guardの有効化」をクリックします。
> 
> OCI DatabaseでのData Guardの作り方（VM）
> https://qiita.com/fujid/items/e2a7186f1b5e74be9d78

![EnableDataGuard.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/7c9227b8-9bee-1f46-df45-26c8d8d53f85.jpeg)

しばらく待つと Data Guard が構成されるので、dgmgrlコマンドで様子を確認してみます。

```sql
[oracle@ayudbcs1 ~]$ dgmgrl
：
DGMGRL> CONNECT SYS/########@ayudbcs2.ayuprvsubnet2.ayuvcn1.oraclevcn.com:1521/ayucdb1_nrt18j.ayuprvsubnet2.ayuvcn1.oraclevcn.com
DGMGRL> SHOW CONFIGURATION;

Configuration - ayucdb1_nrt1fg_ayucdb1_nrt18j

  Protection Mode: MaxPerformance
  Members:
  ayucdb1_nrt1fg - Primary database
    ayucdb1_nrt18j - Physical standby database

Fast-Start Failover:  Disabled

Configuration Status:
SUCCESS   (status updated 14 second ago)

DGMGRL>
```

無事 Data Guard が有効化されてますやね彡(^)(^)
この環境では DB #1 が ayucdb1_nrt1fg、DB #2 が ayucdb1_nrt18j になります。

# 2. ロールベース・サービスの登録

srvctlコマンドでロールベース・サービスを (GI = Grid Infrastructure の) Clusterware に
登録します。DB #1(Primary), DB #2(Standby) のそれぞれで実行して、サービスを登録します。

> Oracle Real Application Clusters 管理およびデプロイメント・ガイド 19c
> A.9.103 srvctl add service
> https://docs.oracle.com/cd/F19136_01/racad/server-control-utility-reference.html#GUID-EC1BA6D7-D538-4E11-9B31-C59389FDF93B
> ：
> -role {PRIMARY | PHYSICAL_STANDBY | LOGICAL_STANDBY | SNAPSHOT_STANDBY}
> Oracle Data Guard構成でのデータベースのロールを指定します。デフォルトはPRIMARYです。
> ：

コマンドは以下の通り、-roleパラメータがポイントで DB が PRIMARY の時だけ起動するサービス彡(ﾟ)(ﾟ)

```shell
# DB #1(Primary, ayucdb1_nrt1fg) 
srvctl add service -db ayucdb1_nrt1fg -service ayudbcs_primary2 -pdb ayupdb1 -role PRIMARY
```

```shell
# DB #2(Standby, ayucdb1_nrt18j) 
srvctl add service -db ayucdb1_nrt18j -service ayudbcs_primary2 -pdb ayupdb1 -role PRIMARY
```

DB #1(Primary, ayucdb1_nrt1fg) で登録したサービスを開始します。

```shell
# DB #1(Primary, ayucdb1_nrt1fg) 
srvctl start service -db ayucdb1_nrt1fg -service ayudbcs_primary2
```

DB #1 のリスナーに起動したサービスが登録されているのを確認します。

```
# DB #1(Primary, ayucdb1_nrt1fg) 
lsnrctl status

LSNRCTL for Linux: Version 19.0.0.0.0 - Production on 31-MAR-2021 04:50:37
：
Service "ayudbcs_primary2.ayuprvsubnet2.ayuvcn1.oraclevcn.com" has 1 instance(s).
  Instance "ayucdb1", status READY, has 2 handler(s) for this service...
：
```

ロールベース・サービスの注意事項として、ロールベース・サービスは Data Guard Broker と
GI(Grid Infrastructure, or Restart) が連携して制御されます。従って GI(or Restart) と Broker との併用が必須です。

> Oracle Data Guard Broker 19c
> 5.6.1.2 データベース・サービスの構成要件
> https://docs.oracle.com/cd/F19136_01/dgbkr/using-data-guard-broker-to-manage-switchovers-failovers.html#GUID-05918DD1-FB0F-435B-873B-A43BEC1C7638

# 3. ロールベース・サービスへの接続文字列構成(※接続時フェイルオーバーを有効化した書き方)

クライアントの tnsnames.ora を編集して、ロールベース・サービスへの接続文字列を構成します。

接続時フェイルオーバーで DB #1(Primary)側への接続を失敗した時に、
DB #2(旧Standby、接続時には新Primary) に接続をフェイルオーバーするように記述するのがポイント
彡(ﾟ)(ﾟ)

> Oracle Database Net Servicesリファレンス 19c
> 6.8.2 FAILOVER
> https://docs.oracle.com/cd/F19136_01/netrf/local-naming-parameters-in-tns-ora-file.html#GUID-4A20F0A2-EDCD-4006-9177-2EA4B12D656D

```sql
AYUDBCS_PRIMARY2=(
  DESCRIPTION_LIST=
    (LOAD_BALANCE=OFF)(FAILOVER=ON)
    (
      DESCRIPTION=
        (CONNECT_TIMEOUT=5)(TRANSPORT_CONNECT_TIMEOUT=5)(RETRY_DELAY=3)(RETRY_COUNT=3)(ENABLE=BROKEN)
        (ADDRESS_LIST=
          (ADDRESS=(PROTOCOL=TCP)(HOST=ayudbcs1-scan.ayuprvsubnet2.ayuvcn1.oraclevcn.com)(PORT=1521))
        )
        (CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=ayudbcs_primary2.ayuprvsubnet2.ayuvcn1.oraclevcn.com))
    )
    (
      DESCRIPTION=
        (CONNECT_TIMEOUT=5)(TRANSPORT_CONNECT_TIMEOUT=5)(RETRY_DELAY=3)(RETRY_COUNT=3)(ENABLE=BROKEN)
        (ADDRESS_LIST=
          (ADDRESS=(PROTOCOL=TCP)(HOST=ayudbcs2-scan.ayuprvsubnet2.ayuvcn1.oraclevcn.com)(PORT=1521))
        )
        (CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=ayudbcs_primary2.ayuprvsubnet2.ayuvcn1.oraclevcn.com))
    )
)
```

上記の書き方だと、まず 1番目のDESCRIPTION(DB #1へのエントリ) に接続を試みて、
失敗すると 2番目のDESCRIPTION(DB #2へのエントリ)に接続を試みます。

# 4. ロールベース・サービスへの接続確認(DB #1 が PRIMARY)

まずはロールの確認、DB #1(ayucdb1_nrt1fg) が PRIMARYロール なのを確認します。

```sql
dgmgrl
CONNECT SYS/########@ayudbcs2.ayuprvsubnet2.ayuvcn1.oraclevcn.com:1521/ayucdb1_nrt18j.ayuprvsubnet2.ayuvcn1.oraclevcn.com
SHOW CONFIGURATION;

Configuration - ayucdb1_nrt1fg_ayucdb1_nrt18j

  Protection Mode: MaxPerformance
  Members:
  ayucdb1_nrt1fg - Primary database
    ayucdb1_nrt18j - Physical standby database

Fast-Start Failover:  Disabled

Configuration Status:
SUCCESS   (status updated 14 second ago)
```

DB #1 が Primary の状態で #3. の接続文字列でロールベース・サービスに接続します。

```sql
sqlplus /nolog
CONNECT AYSHIBAT/########@AYUDBCS_PRIMARY2
SET LINESIZE 300;
SET PAGESIZE 100;
COLUMN HOST_NAME FORMAT A50;
COLUMN MY_SERVICE FORMAT A80;
SELECT NAME, DB_UNIQUE_NAME, DATABASE_ROLE, OPEN_MODE FROM V$DATABASE;
SELECT INSTANCE_NAME, HOST_NAME FROM V$INSTANCE;
SELECT SYS_CONTEXT('USERENV', 'SERVICE_NAME') AS MY_SERVICE FROM DUAL;
SHOW CON_NAME;
```

結果は以下の通り、DB #1(ayucdb1_nrt1fg) に接続できてますやね彡(^)(^)

```sql
SQL*Plus: Release 19.0.0.0.0 - Production on Wed Mar 31 05:23:58 2021
：
SQL> CONNECT AYSHIBAT/########@AYUDBCS_PRIMARY2
Connected.
SQL> SET LINESIZE 300;
SQL> SET PAGESIZE 100;
SQL> COLUMN HOST_NAME FORMAT A50;
SQL> COLUMN MY_SERVICE FORMAT A80;
SQL> SELECT NAME, DB_UNIQUE_NAME, DATABASE_ROLE, OPEN_MODE FROM V$DATABASE;

NAME      DB_UNIQUE_NAME                 DATABASE_ROLE    OPEN_MODE
--------- ------------------------------ ---------------- --------------------
AYUCDB1   ayucdb1_nrt1fg                 PRIMARY          READ WRITE

SQL> SELECT INSTANCE_NAME, HOST_NAME FROM V$INSTANCE;

INSTANCE_NAME    HOST_NAME
---------------- --------------------------------------------------
ayucdb1          ayudbcs1

SQL> SELECT SYS_CONTEXT('USERENV', 'SERVICE_NAME') AS MY_SERVICE FROM DUAL;

MY_SERVICE
--------------------------------------------------------------------------------
ayudbcs_primary2.ayuprvsubnet2.ayuvcn1.oraclevcn.com

SQL> SHOW CON_NAME;

CON_NAME
------------------------------
AYUPDB1
SQL>
```

# 5. スイッチオーバー(ロール変換)の実行 ※追記あり

※追記：OCI DBCS におけるスイッチオーバー、フェイルオーバーはWebコンソール または OCI CLI を
使うべきである、という指摘がありました。詳しくは # 8. を参照……。

dgmgrl の SWITCHOVERコマンド で DB #1(ayucdb1_nrt1fg) と DB #2(ayucdb1_nrt18j) のロールを入れ替えます。
Data Guard の手動スイッチは超面倒なんですが、dgmgrl のスイッチオーバーはコマンド一発で超らくちん彡(^)(^)

```sql
dgmgrl
CONNECT SYS/########@ayudbcs2.ayuprvsubnet2.ayuvcn1.oraclevcn.com:1521/ayucdb1_nrt18j.ayuprvsubnet2.ayuvcn1.oraclevcn.com
SWITCHOVER to ayucdb1_nrt18j;
SHOW CONFIGURATION;
```

結果は以下の通り、きっちりロール(Primary, Standby)が入れ替わってますやね彡(^)(^)

```sql
[oracle@ayudbcs1 ~]$ dgmgrl
DGMGRL for Linux: Release 19.0.0.0.0 - Production on Wed Mar 31 05:17:32 2021
:
DGMGRL> CONNECT SYS/########@ayudbcs2.ayuprvsubnet2.ayuvcn1.oraclevcn.com:1521/ayucdb1_nrt18j.ayuprvsubnet2.ayuvcn1.oraclevcn.com
Connected to "ayucdb1_nrt18j"
Connected as SYSDBA.
DGMGRL> SWITCHOVER to ayucdb1_nrt18j;
Performing switchover NOW, please wait...
New primary database "ayucdb1_nrt18j" is opening...
Oracle Clusterware is restarting database "ayucdb1_nrt1fg" ...
Connected to "ayucdb1_nrt1fg"
Connected to "ayucdb1_nrt1fg"
Switchover succeeded, new primary is "ayucdb1_nrt18j"
DGMGRL> SHOW CONFIGURATION;

Configuration - ayucdb1_nrt1fg_ayucdb1_nrt18j

  Protection Mode: MaxPerformance
  Members:
  ayucdb1_nrt18j - Primary database
    ayucdb1_nrt1fg - Physical standby database

Fast-Start Failover:  Disabled

Configuration Status:
SUCCESS   (status updated 15 seconds ago)
```

# 6. ロールベース・サービスへの接続確認(DB #2 が PRIMARY)

DB #2 のリスナーに起動したサービスが登録されているのを確認します。

```
# DB #2(Primary, ayucdb1_nrt18j) 
lsnrctl status

LSNRCTL for Linux: Version 19.0.0.0.0 - Production on 31-MAR-2021 04:50:37
：
Service "ayudbcs_primary2.ayuprvsubnet2.ayuvcn1.oraclevcn.com" has 1 instance(s).
  Instance "ayucdb1", status READY, has 2 handler(s) for this service...
：
```

DB #2 が Primary の状態で #3. の接続文字列でロールベース・サービスに接続します。

```sql
sqlplus /nolog
CONNECT AYSHIBAT/########@AYUDBCS_PRIMARY2
SET LINESIZE 300;
SET PAGESIZE 100;
COLUMN HOST_NAME FORMAT A50;
COLUMN MY_SERVICE FORMAT A80;
SELECT NAME, DB_UNIQUE_NAME, DATABASE_ROLE, OPEN_MODE FROM V$DATABASE;
SELECT INSTANCE_NAME, HOST_NAME FROM V$INSTANCE;
SELECT SYS_CONTEXT('USERENV', 'SERVICE_NAME') AS MY_SERVICE FROM DUAL;
SHOW CON_NAME;
```

結果は以下の通り、DB #2(ayucdb1_nrt18j) に接続できてますやね彡(^)(^)

```sql
SQL*Plus: Release 19.0.0.0.0 - Production on Wed Mar 31 05:23:58 2021
：
SQL> CONNECT AYSHIBAT/########@AYUDBCS_PRIMARY2
Connected.
SQL> SET LINESIZE 300;
SQL> SET PAGESIZE 100;
SQL> COLUMN HOST_NAME FORMAT A50;
SQL> COLUMN MY_SERVICE FORMAT A80;
SQL> SELECT NAME, DB_UNIQUE_NAME, DATABASE_ROLE, OPEN_MODE FROM V$DATABASE;

NAME      DB_UNIQUE_NAME                 DATABASE_ROLE    OPEN_MODE
--------- ------------------------------ ---------------- --------------------
AYUCDB1   ayucdb1_nrt18j                 PRIMARY          READ WRITE

SQL> SELECT INSTANCE_NAME, HOST_NAME FROM V$INSTANCE;

INSTANCE_NAME    HOST_NAME
---------------- --------------------------------------------------
ayucdb1          ayudbcs2

SQL> SELECT SYS_CONTEXT('USERENV', 'SERVICE_NAME') AS MY_SERVICE FROM DUAL;

MY_SERVICE
--------------------------------------------------------------------------------
ayudbcs_primary2.ayuprvsubnet2.ayuvcn1.oraclevcn.com

SQL> SHOW CON_NAME;

CON_NAME
------------------------------
AYUPDB1
SQL>
```

# 7. まとめ

ロールベース・サービス と 接続時フェイルオーバー の組み合わせで、クライアントの
接続文字列を変更せずに Data Guard の PRIMARYサイト に透過的に接続できる！
彡(^)(^)

これで仕込みは完了、本当にやりたかった事(AC)は次回以降に……彡(ﾟ)(ﾟ)

# 8. 追記：Webコンソール と OCI CLI による OCI DBCS の Data Guard ロール変換(スイッチオーバー／フェイルオーバー)

OCI DBCS においては Data Guard のスイッチオーバー や フェイルオーバー は Webコンソール や OCI CLI で
やるべきである、という指摘がありました。そうしないと画面の状態と実際の DB の状態が異なってしまうそうな。
なるぺそ彡(ﾟ)(ﾟ)

---

> Oracle Data Guardの使用
> https://docs.oracle.com/ja-jp/iaas/Content/Database/Tasks/usingdataguard.htm
> ：
> データベースのスイッチオーバーを実行するには
> ：
> 5. スイッチオーバーを実行するData Guardアソシエーションについて、
> 「アクション」アイコン(3つのドット)をクリックし、「スイッチオーバー」をクリックします。
> ：
> データベースのフェイルオーバーを実行するには
> ：
> 5. フェイルオーバーを実行するData Guardアソシエーションについて、「フェイルオーバー」をクリックします。
> ：

---

> Docs >> db >> data-guard-association >> switchover
> https://docs.oracle.com/en-us/iaas/tools/oci-cli/2.22.1/oci_cli_docs/cmdref/db/data-guard-association/switchover.html
> Usage
> oci db data-guard-association switchover [OPTIONS]
> ：

---

> Docs >> db >> data-guard-association >> failover
> https://docs.oracle.com/en-us/iaas/tools/oci-cli/2.22.1/oci_cli_docs/cmdref/db/data-guard-association/failover.html
> Usage
> oci db data-guard-association failover [OPTIONS]

---

皆さま、お気を付けくださいませ。(｀･ω･)ゞ