Oracle Database 21c DG PDB の構築について

## はじめに

Oracle 21c (21.7 ～) の新機能でPDB単位の可用性を高める Data Guard per Pluggable Database (DG PDB構成)が利用可能になりました。 従来の Data Guard と比較すると現時点では制約も多いようですが、実際の環境構築手順を確認しつつ簡単に動きも確認します。
<https://docs-uat.us.oracle.com/en/database/oracle/oracle-database/21/nfcon/new-features-21c-release-updates.html#GUID-92157A6A-9333-4FD0-AC21-FCDACB6CF10D>

## DG PDB の概要
Data Guard (または、Active Data Guard)は、Database 単位で構成されるので、従来の構成では Primary CDBと Standby CDBが存在し連携しますが、DG PDB構成では2つの Primary CDB が存在し、その各CDBで稼働する2つのPDBが Primary および Standbyロールで稼働する認識です。そのため、Primary PDB / Standby PDBのロール変更(Switch Over や Fail Over)は他の稼働中であるPDBに影響を与えません。
今回は、まず PDBを1つだけ持ったCDB と PDBを持たない CDBを準備し、DG PDB構成を作ります。
以下、テスト環境の情報です。


|  | Site 1 | Site 2 |
| :--- | :---: | ---: |
| ホスト名 | test24 | test25 |
| Oracle Version | 21.10 | 21.10 |
| CDB 名 | o2124 | o2125 |
| PDB 名 | pdb1 | (pdb2) 未作成 |

![DGPDB_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470713/b36f037e-2651-b7c2-69fc-8940bc17e497.png)
参考にしたサイトURL
<https://blogs.oracle.com/maa/post/dgpdb-available-today>
<https://docs.oracle.com/cd/F39414_01/dgbkr/managing-oracle-data-guard-broker-dgpdb-configuration-members.html#GUID-FC91CF75-0EF8-43C2-80C4-55B12C029E30>

## DG PDB 環境構築手順
### 1) Data Guard Broker 関連パラメータの確認
ホスト test24で以下を確認します。 今回はDG_BROKER_CONFIG_FILEはそのままで進めます。
```
SQL> show parameter DG_BROKER_START
 
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
dg_broker_start                      boolean     FALSE
SQL>show parameter DG_BROKER_CONFIG_FILE1
 
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
dg_broker_config_file1               string      /u01/app/oracle/homes/OraDB21Home1/dbs/dr1o2124.dat

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
dg_broker_config_file2               string      /u01/app/oracle/homes/OraDB21Home1/dbs/dr2o2124.dat
```

同様に、test25でもData Guard Broker 関連パラメータの確認をします。
```
SQL>show parameter DG_BROKER_START
 
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
dg_broker_start                      boolean     FALSE
SQL>show parameter DG_BROKER_CONFIG_FILE1
 
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
dg_broker_config_file1               string      /u01/app/oracle/homes/OraDB21Home1/dbs/dr1o2125.dat
 
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
dg_broker_config_file2               string      /u01/app/oracle/homes/OraDB21Home1/dbs/dr2o2125.dat
```

### 2)	両インスタンスで DG Broker を有効にする
```
SQL> ALTER SYSTEM SET DG_BROKER_START=TRUE;
システムが変更されました。
```

※	データベース・インスタンスの**次回起動時**にOracle Data Guard Brokerが自動的に起動することが保証されます。 
<https://docs.oracle.com/cd/F39414_01/dgbkr/managing-oracle-data-guard-broker-configurations.html#GUID-1CB8734A-B5D9-4B65-A950-72ADDF632DCE>
つまり有効にするために両インスタンスの再起動が必要です。

### 3)	各CDBにスタンバイREDOログを用意する
両環境のスタンバイREDOログ情報を確認しておきます。
```
SQL> show parameter standby_file_management
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
standby_file_management  string      MANUAL

SQL> alter system set standby_file_management = AUTO scope = both;
システムが変更されました。
SQL> select group#,thread#,bytes from v$standby_log;
レコードが選択されませんでした。
SQL> select group#,thread#,bytes from v$log;
 
    GROUP#    THREAD#      BYTES
---------- ---------- ----------
         1          1  209715200
         2          1  209715200
         3          1  209715200
```
test24 および test25でスタンバイREDOの追加を実行します。
```
SQL> ALTER DATABASE ADD STANDBY LOGFILE size 209715200;
データベースが変更されました。
SQL> ALTER DATABASE ADD STANDBY LOGFILE size 209715200;
データベースが変更されました。
SQL> ALTER DATABASE ADD STANDBY LOGFILE size 209715200;
データベースが変更されました。
SQL> ALTER DATABASE ADD STANDBY LOGFILE size 209715200;
データベースが変更されました。
SQL> select group#,thread#,bytes from v$standby_log;
    GROUP#    THREAD#      BYTES
---------- ---------- ----------
         4          0  209715200
         5          0  209715200
         6          0  209715200
         7          0  209715200
```
### 4)	test24 および test25 の tnsnames.ora 編集
両ノードで同じ内容に編集します。
```
O2124 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = test24.jp.xxx.com)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = o2124)
    )
  )
 
O2125 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = test25.jp.xxx.com)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = o2125)
    )
  )
```
### 5)	test24 および test25で Wallet の設定を実施
wallet の作成をします。(※以下、SIDとなっているところはo2124かo2125の何れかに置き換えて下さい)
```
$ mkstore -wrl /u01/app/oracle/admin/SID/wallet -create
Enter password: Wallet本体のパスワードを入力 : Welcome123## (任意)
Enter password again: Wallet本体のパスワードを入力(確認用) : Welcome123## (任意)
```
以下のファイルが作成されます。
```
[oracle@test24 admin]$ ls -l /u01/app/oracle/admin/SID/wallet/
合計 8
-rw------- 1 oracle oinstall 194  6月 22 08:54 cwallet.sso
-rw------- 1 oracle oinstall   0  6月 22 08:54 cwallet.sso.lck
-rw------- 1 oracle oinstall 149  6月 22 08:54 ewallet.p12
-rw------- 1 oracle oinstall   0  6月 22 08:54 ewallet.p12.lck
```
環境変数 TNS_ADMIN のセットをしておきます。
```
export TNS_ADMIN=/u01/app/oracle/admin/SID/wallet
```
test24/25でCredentialをそれぞれ作成します。
sys ユーザに対してwalletを作成しています。
```
$ mkstore -wrl /u01/app/oracle/admin/SID/wallet -createCredential o2124 sys
Your secret/Password is missing in the command line
Enter your secret/Password: 接続DBユーザ(sys)のパスワード
Re-enter your secret/Password: 接続DBユーザ(sys)のパスワード
Enter wallet password: Wallet本体のパスワード
```
```
$ mkstore -wrl /u01/app/oracle/admin/SID/wallet -createCredential o2125 sys
Your secret/Password is missing in the command line
Enter your secret/Password: 接続DBユーザ(sys)のパスワード
Re-enter your secret/Password: 接続DBユーザ(sys)のパスワード
Enter wallet password: Wallet本体のパスワード
```
sqlnet.ora を編集します。
```
WALLET_LOCATION=(SOURCE=(METHOD=FILE)(METHOD_DATA=(DIRECTORY=/u01/app/oracle/admin/SID/wallet)))
SQLNET.WALLET_OVERRIDE=TRUE
```
### 6)	Broker 操作による site1 および site2 を作成 (test24で実行)
```
dgmgrl sys/oracle
[oracle@test24 admin]$ dgmgrl sys/oracle
DGMGRL for Linux: Release 21.0.0.0.0 - Beta on 火 6月 20 10:20:07 2023
Version 21.10.0.0.0
 Copyright (c) 1982, 2021, Oracle and/or its affiliates.  All rights reserved.
 
DGMGRLへようこそ。詳細は"help"と入力してください。
"o2124"に接続しました
SYSDBAとして接続しました。
DGMGRL> CREATE CONFIGURATION site1 AS PRIMARY DATABASE IS o2124 CONNECT IDENTIFIER IS o2124;
"o2124"に接続しました
構成"site1"が、プライマリ・データベース"o2124"とともに作成されました
```
```
DGMGRL> show configuration verbose;
構成 - site1
  保護モード: MaxPerformance
  メンバー:
  o2124 - プライマリ・データベース
 
  プロパティ:
    FastStartFailoverThreshold      = '30'
    OperationTimeout                = '30'
    TraceLevel                      = 'USER'
    FastStartFailoverLagLimit       = '30'
    CommunicationTimeout            = '180'
    ObserverReconnect               = '0'
    ObserverPingInterval            = '0'
    ObserverPingRetry               = '0'
    FastStartFailoverAutoReinstate  = 'TRUE'
    FastStartFailoverPmyShutdown    = 'TRUE'
    BystandersFollowRoleChange      = 'ALL'
    ObserverOverride                = 'FALSE'
    ExternalDestination1            = ''
    ExternalDestination2            = ''
    PrimaryLostWriteAction          = 'CONTINUE'
    ConfigurationWideServiceName    = 'o2124_CFG'
    ConfigurationSimpleName         = 'site1'
    DrainTimeout                    = '0'
 
ファスト・スタート・フェイルオーバー:  Disabled

構成ステータス:
DISABLED
```
※ DISABLEDとなっている事にご注意下さい。以下で構成ステータスは有効になりました。
```
DGMGRL>disable configuration;
DGMGRL>enable configuration all;
DGMGRL>show configuration
構成 - site1
 
  保護モード: MaxPerformance
  メンバー:
  o2124 - プライマリ・データベース
 
ファスト・スタート・フェイルオーバー:  Disabled
 
構成ステータス:
SUCCESS   (ステータスは17秒前に更新されました)
```
続けて site2 を作成します。
```
DGMGRL> CREATE CONFIGURATION site2 AS PRIMARY DATABASE IS o2125 CONNECT IDENTIFIER IS o2125;
"o2125"に接続しました
構成"site2"が、プライマリ・データベース"o2125"とともに作成されました
```
```
DGMGRL> show configuration verbose;
構成 - site2
  保護モード: MaxPerformance
  メンバー:
  o2125 - プライマリ・データベース
 
  プロパティ:
    FastStartFailoverThreshold      = '30'
    OperationTimeout                = '30'
    TraceLevel                      = 'USER'
    FastStartFailoverLagLimit       = '30'
    CommunicationTimeout            = '180'
    ObserverReconnect               = '0'
    ObserverPingInterval            = '0'
    ObserverPingRetry               = '0'
    FastStartFailoverAutoReinstate  = 'TRUE'
    FastStartFailoverPmyShutdown    = 'TRUE'
    BystandersFollowRoleChange      = 'ALL'
    ObserverOverride                = 'FALSE'
    ExternalDestination1            = ''
    ExternalDestination2            = ''
    PrimaryLostWriteAction          = 'CONTINUE'
    ConfigurationWideServiceName    = 'o2125_CFG'
    ConfigurationSimpleName         = 'site2'
    DrainTimeout                    = '0'
 
ファスト・スタート・フェイルオーバー:  Disabled
 
構成ステータス:
DISABLED
```
ステータスが同様にDISABLEDになっていれば、site1同様に以下を実行すると良いでしょう。

DGMGRL>disable configuration;
DGMGRL>enable configuration all;

### 7)	Broker 操作で o2124に site2 を追加
```
[oracle@test24 ~]$ dgmgrl /
DGMGRL for Linux: Release 21.0.0.0.0 - Production on 火 6月 27 09:39:41 2023
Version 21.10.0.0.0
 
Copyright (c) 1982, 2021, Oracle and/or its affiliates.  All rights reserved.
 
DGMGRLへようこそ。詳細は"help"と入力してください。
"o2124"に接続しました
SYSDGとして接続しました。
DGMGRL> add configuration site2 connect identifier is o2125;
構成site2は追加されました。
```
```
DGMGRL> show configuration verbose;
構成 - site1
 
  保護モード: MaxPerformance
  メンバー:
  o2124 - プライマリ・データベース
  o2125 - site2構成のプライマリ・データベースはです
 
  プロパティ:
    FastStartFailoverThreshold      = '30'
    OperationTimeout                = '30'
    TraceLevel                      = 'USER'
    FastStartFailoverLagLimit       = '30'
    CommunicationTimeout            = '180'
    ObserverReconnect               = '0'
    ObserverPingInterval            = '0'
    ObserverPingRetry               = '0'
    FastStartFailoverAutoReinstate  = 'TRUE'
    FastStartFailoverPmyShutdown    = 'TRUE'
    BystandersFollowRoleChange      = 'ALL'
    ObserverOverride                = 'FALSE'
    ExternalDestination1            = ''
    ExternalDestination2            = ''
    PrimaryLostWriteAction          = 'CONTINUE'
    ConfigurationWideServiceName    = 'o2124_CFG'
    ConfigurationSimpleName         = 'site1'
    DrainTimeout                    = '0'
 
ファスト・スタート・フェイルオーバー:  Disabled
 
構成ステータス:
SUCCESS

DGMGRL> show configuration verbose site2;

構成 - site2
プライマリ・データベース: o2125
 
  プロパティ:
    DGConnectIdentifier             = ''
    LogShipping                     = 'ON'
    LogXptMode                      = 'ASYNC'
    DelayMins                       = '0'
    Binding                         = 'optional'
    MaxFailure                      = '0'
    ReopenSecs                      = '300'
    NetTimeout                      = '30'
    RedoCompression                 = 'DISABLE'
 
構成site2ステータス:
SUCCESS
```
### 8)	Broker 操作でPDB2を追加する　(test24で実施)
```
DGMGRL> ADD PLUGGABLE DATABASE 'pdb2' AT 'o2125' SOURCE IS 'pdb1' AT 'o2124' PDBFileNameConvert IS "'/u01/app/oracle/oradata/O2124/pdb1', '/u01/app/oracle/oradata/O2125/pdb2'";
"o2125"に接続しました
"o2124"に接続しました
"o2125"に接続しました

プラガブル・データベース"PDB2"が追加されました
```
```
DGMGRL> show pluggable database pdb1 at o2124;
 
データベース'o2124'のプラガブル・データベース'pdb1'
 
  Data Guardロール: Primary
  Con_ID:              3
  アクティブなターゲット: con_id 3 at o2125
 
プラガブル・データベースのステータス:
SUCCESS
```
```
DGMGRL> show pluggable database pdb2 at o2125;
"o2125"に接続しました
 
データベース'o2125'のプラガブル・データベース'pdb2'
 
  Data Guardロール: Physical Standby
  Con_ID:              3
  ソース:           con_id 3 at o2124
  トランスポート・ラグ: 0 秒 (47秒前に計算されました)
  意図した状態   APPLY-ON
  適用状態:        実行されていません
 
プラガブル・データベースのステータス:
DGM-5103: one or more data files were not found
ORA-16766: REDO Applyが停止しています
```
この操作により o2125 には PDB2が追加されますが、実データファイルの移植までは行いません。
そのため REDO Applyが停止状態となっています。

よって、test24のPDB1からデータファイルを移植します。
ここでは、OMFを使用していないため、PDB1を一度closeして静的なファイル・コピーを実施する事でPDBのDuplicate操作とすることにします。(環境や条件に応じてRMANなども活用できると思います)

### 9)	PDB1のデータファイル移植操作とDGPDB構成の完了
test24のPDB1を一度停止(close)します。
```
Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.10.0.0.0
に接続されました。
SQL> alter pluggable database pdb1 close;
 
プラガブル・データベースが変更されました。
 
SQL> show pdbs
 
    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 PDB1                           MOUNTED
```
test24の /u01/app/oracle/oradata/O2124/pdb1 にあるデータファイルを
test25の　/u01/app/oracle/oradata/O2125/pdb2 へcopyし、test24のPDB1(DGPDB Primary)をopenしておきます。
```
[oracle@test24 ~]$ dgmgrl sys/oracle
DGMGRL for Linux: Release 21.0.0.0.0 - Production on 火 6月 27 10:05:52 2023
Version 21.10.0.0.0
 
Copyright (c) 1982, 2021, Oracle and/or its affiliates.  All rights reserved.
 
DGMGRLへようこそ。詳細は"help"と入力してください。
"o2124"に接続しました
SYSDBAとして接続しました。
DGMGRL> enable configuration all;
成功しました。
DGMGRL> show pluggable database pdb1 at o2124;
 
データベース'o2124'のプラガブル・データベース'pdb1'
 
  Data Guardロール: Primary
  Con_ID:              3
  アクティブなターゲット: con_id 3 at o2125
 
プラガブル・データベースのステータス:
SUCCESS
```
```
DGMGRL> show pluggable database pdb2 at o2125;
"o2125"に接続しました
 
データベース'o2125'のプラガブル・データベース'pdb2'
 
  Data Guardロール: Physical Standby
  Con_ID:              3
  ソース:           con_id 3 at o2124
  トランスポート・ラグ: 0 秒 (21秒前に計算されました)
  意図した状態   APPLY-ON
  適用状態:        実行中
  適用インスタンス: o2125
  平均適用頻度:  (不明)
  リアルタイム問合せ: OFF
 
プラガブル・データベースのステータス:
SUCCESS
```
適用も実行中となり、DG PDB環境はここまでで完成になります。

### A)	DGPDBのswitch over を試す
以下はPDB2 (DG PDBのスタンバイ) の状態です。MODEはMOUNTEDとなっています。
``` 
Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production
Version 21.10.0.0.0
に接続されました。
SQL> show pdbs
    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 PDB2                           MOUNTED
``` 
DG Broker からの操作で Switch Over を試します。
``` 
DGMGRL> switchover to pluggable database pdb2 at o2125;
Switchoverの条件を検証中...
 
"o2125"に接続しました
"o2124"に接続しました
  ソース・プラガブル・データベースは、データベース'o2124'の'PDB1'です
 
現在スイッチオーバーを実行しています。お待ちください...
 
  プラガブル・データベース'PDB1'をクローズ中...
  'PDB1'をスタンバイ・ロールに切り替えています...
"o2125"に接続しました
  'PDB2'がすべてのREDOデータをリカバリするのを待機しています...
  'PDB2'でリカバリを停止しています...
  'PDB2'をプライマリ・ロールに変換しています...
  新規プライマリ'PDB2'を開いています...
"o2124"に接続しました
  新規プライマリ'PDB2'からのREDOデータを待機しています...
  新規スタンバイ'PDB1'でリカバリを開始しています...
 
スイッチオーバーに成功しました。新しいプライマリは"PDB2"です
``` 
```  
DGMGRL> show pluggable database pdb1 at o2124;
 
データベース'o2124'のプラガブル・データベース'pdb1'
 
  Data Guardロール: Physical Standby
  Con_ID:              3
  ソース:           con_id 3 at o2125
  トランスポート・ラグ: (不明)
  意図した状態   APPLY-ON
  適用状態:        実行中
  適用インスタンス: o2124
  平均適用頻度:  3 KB/秒
  リアルタイム問合せ: OFF
 
プラガブル・データベースのステータス:
SUCCESS
``` 
``` 
DGMGRL> show pluggable database pdb2 at o2125;
"o2125"に接続しました
 
データベース'o2125'のプラガブル・データベース'pdb2'
 
  Data Guardロール: Primary
  Con_ID:              3
  アクティブなターゲット: con_id 3 at o2124
 
プラガブル・データベースのステータス:
SUCCESS
``` 
test25上のPDB2はSwitch Over後、DG PDBのプライマリとして READ WRITE モードでOpenされます。
一方でPDB1は DG PDBのスタンバイとなり、モードはMOUNTEDです。
``` 
SQL> show pdbs
 
    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 PDB2                           READ WRITE NO
```
```
SQL> show pdbs
 
    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 PDB1                           MOUNTED
```

### B)	DGPDB構成に PDB3を作成する
この状態で o2124 にPDB3をPDB$SEEDからDBCAで作成してみます。
DG PDBが組まれた PDB1およびPDB2へ影響を与えずに、スタンドアロンとしてPDB3が存在できる事を確認します。
ちなみにPDB1は A)によるSwitch Overしたままなので MOUNTED モードのままです。
```
SQL> show pdbs
 
    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 PDB1                           MOUNTED
         4 PDB3                           MOUNTED  ⇦ 作成中
SQL> show pdbs
 
    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 PDB1                           MOUNTED
         4 PDB3                           READ WRITE NO ⇦ 完成
```
![DGPDB_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3470713/26b52faa-0d75-8bce-55af-097470d81fed.png)
```
DGMGRL> show pluggable database  pdb3 at o2124;
データベース'o2124'のプラガブル・データベース'pdb3'
  Data Guardロール: Not Protected
```

## 最後に

制約は幾つかありますが、PDB単位の Data Guard が実装できる事が確認できました。ブログによれば確約はされていないものの、今後制約を緩和するか予定もあるようです。
まだ踏み込んで試してはいませんが、REDO転送は通常のData Guardと同様に行われDG PDBが構成された対象のPDBのみが適用対象となるならば CDBに含まれる PDBの数が多いほどREDO転送に負荷がかかる事が推測できます。ADGスタンバイの様に Read Only で使用できない事もあり、求められる可用性・運用性とコストのバランスはある程度限定されるかも知れません。