Active Data Guard DML Redirectを試す（Oracle Database 19c) 

Oracle Database 19cの新機能であるActive Data Guard DML Redirect機能を試してみました。この機能を使うと、Data Guardスタンバイ・インスタンス上で更新系DMLを実行できるようになります。実際には更新系DML文は、プライマリ・インスタンス上に転送（Redirect）／実行され、実行結果のREDO情報がスタンバイ・インスタンスで確認できるようになります。

# 準備
Redirect DML機能の利用に特別な準備は必要ありません。通常と同じようにActive Data Guardインスタンスを構成します。常時Redirect DML機能を有効にする場合は、スタンバイ・インスタンスの初期化パラメータadg_redirect_dmlをTRUEに指定します（デフォルトFALSE)。後述の理由にリアルタイム適用が有効になっていることが望まれます。

```SQL: 準備
SQL> SHOW PARAMETER adg_redirect_dml

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
adg_redirect_dml                     boolean     FALSE
SQL> 
SQL> SELECT process, pid, status, thread#, sequence# FROM V$MANAGED_STANDBY WHERE process='MRP0';

PROCESS   PID                      STATUS          THREAD#  SEQUENCE#
--------- ------------------------ ------------ ---------- ----------
MRP0      159079                   APPLYING_LOG          1         61
```

# 実行
Active Data Guardのスタンバイ・インスタンスは通常Read Onlyモードで起動されています。このため、スタンバイ・インスタンス上で実行された更新系DMLはエラーになります。

```SQL: 実行
SQL> CONNECT scott/tiger
Connected.
SQL> SELECT * FROM data1;

        C1 C2
---------- ----------
       100 primary1

SQL> INSERT INTO data1 VALUES (200, 'standby2');
INSERT INTO data1 VALUES (200, 'standby2')
            *
ERROR at line 1:
ORA-16000: database or pluggable database open for read-only access
```

しかしALTER SESSION ENABLE ADG_REDIRECT_DML文を実行することで、DML文はプライマリ・インスタンスに転送されることになります。

```SQL: 転送
SQL> ALTER SESSION ENABLE ADG_REDIRECT_DML;

Session altered.

SQL> INSERT INTO data1 VALUES (200, 'standby2');

1 row created.

SQL> COMMIT;

Commit complete.

SQL> SELECT * FROM data1;

        C1 C2
---------- ----------
       100 primary1
       200 standby2
```

マニュアルに記述が見つからないのですが、プライマリ・インスタンスへの接続情報は、初期化パラメーターfal_serverの値を使っているようです。このため、初期化パラメーターfal_serverの設定が指定されていない場合、更新系DMLはエラーになります。

```SQL: fal_server せつぞｋ
SQL> SHOW PARAMETER fal_server

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
fal_server                           string
SQL>
SQL> INSERT INTO data1 VALUES (100, 'standby1');
INSERT INTO data1 VALUES (100, 'standby1')
*
ERROR at line 1:
ORA-16397: statement redirection from Oracle Active Data Guard standby database
to primary database failed

SQL> !oerr ora 16397
16397, 00000, "statement redirection from Oracle Active Data Guard standby database to primary database failed"
// *Cause:  The statement redirection failed because of one of the following reasons:
//          1. The primary database connect string was not established.
//          2. The primary database could not be reached.
//          3. The undo-mode or incarnation were not the same.
//          4. The current user and logged-in user were not the same.
//          5. Redirecting CREATE TABLE AS SELECT (CTAS) of the global temporary
//             table was not supported.
//          6. Redirecting PL/SQL execution having bind variable was not supported.
// *Action: Run the statement after fixing the condition that caused the failure.

```

# 制約
スタンバイ・インスタンス上で実行された更新系DMLは、プライマリ・インスタンスへ転送／実行され、スタンバイ・インスタンスにREDO転送／適用が完了するまでユーザーに処理を返さないように見えます。このためリアルタイム適用の運用が必須になると思われます。
PL/SQLプロシージャによる更新は別の制御が必要になります。こちらは別途検証しようと思います。