OCI BaseDB の Active Data Guard と UCP(ucp.jar) の Application Continuity で Switchover しつつトランザクション続行してみる。(Oracle Cloud Infrastructure)

この記事は JPOUG Advent Calendar 2023 12日目(※) および Oracle Cloud Infrastructure Advent Calendar 2023 13日目 の記事となります。※もともと13日目でしたがJPOUG側は入れ替えました。
彡(ﾟ)(ﾟ)

https://adventar.org/calendars/8844

https://qiita.com/advent-calendar/2023/oci

Application Continuity はトランザクションのエラーが発生した際に、そのトランザクションをバックグラウンドで再実行してエラーをクライアントから隠蔽しつつ可用性を向上する機能です。

ライセンスのマニュアルに記載がありますが Application Continuity は RAC, RAC One Node, Active Data Guard で利用可能です。

> Oracle Database データベース・ライセンス情報ユーザー・マニュアル 19c
> 1.3 Oracle Database製品で許可される機能、オプションおよびManagement Pack
> https://docs.oracle.com/cd/F19136_01/dblic/Licensing-Information.html#GUID-B6113390-9586-46D7-9008-DCC9EDA45AB4
> アプリケーション・コンティニュイティ
> EEおよびEE-ES: Oracle Active Data Guardオプション、Oracle RAC One NodeオプションまたはOracle Real Application Clustersオプションが必要

本記事では OCI BaseDB EEEP の ActiveData Guard で Switchover した際に発生する使用不可時間を Application Continuity でエラー無くトランザクションを続行できるかを検証してみますやで。
彡(ﾟ)(ﾟ)


# 1. 参考記事／マニュアル

下記の記事とマニュアルを参考にしています。

> Application Continuity を Java の UCP(ucp.jar) と Autonomous Database の ATP で試してみる。(Oracle Cloud Infrastructure)
> https://qiita.com/ora_gonsuke777/items/5e348a4f444b2d3643d0
> 
> アプリケーション・コンティニュイティを使用するOracle RACのサービスの作成
> https://docs.oracle.com/cd/F19136_01/racad/ensuring-application-continuity.html#GUID-9DAE9270-A5BC-4A0F-9A55-D9DCFC0A9BF5
> 
> 28.1 Java用のアプリケーション・コンティニュイティに対するOracle JDBCの構成について
> https://docs.oracle.com/cd/E82638_01/jjdbc/application-continuity.html#GUID-9298BB8C-0E93-44BF-BA26-A615940C0C84


# 2. 構成図

以下の構成図となります。OS は Oracle Linux 8 となります。Private Compute の Java + UCP(ucp.jar) から EEEP/Active Data Guard構成の BaseDB に接続して Application Continuity を検証します。

![ACwDG000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/db58c463-eea3-c11b-c7dd-dc85bd7c8177.png)

これらのリソースやDBユーザー等は作成済みのものとします。下記記事等を参照して下さい。

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

https://qiita.com/ora_gonsuke777/items/7f705f29fb65050bf295

# 3. JDK(Oracle JDK), JDBC Thin Driver, UCP Driver のダウンロード

Private Compute で JDK(Oracle JDK), JDBC Thin Driver, UCP Driver をダウンロード＆展開します。

> Java Downloads
> https://www.oracle.com/jp/java/technologies/downloads/
> 
> Oracle Database JDBC driver and Companion Jars Downloads
> https://www.oracle.com/database/technologies/appdev/jdbc-downloads.html

今では色々と緩和されて認証等無しでダウンロードできるようになりました。wget で JDK(Oracle JDK 21), JDBC Thin Driver, UCP(ucp.jar) をダウンロードして展開/配置します。

```batchfile
cd /home/opc
mkdir work
cd ./work
wget https://download.oracle.com/java/21/latest/jdk-21_linux-x64_bin.tar.gz
tar xvzf jdk-21_linux-x64_bin.tar.gz
mkdir jdbc
cd jdbc
wget https://download.oracle.com/otn-pub/otn_software/jdbc/233/ojdbc11.jar
wget https://download.oracle.com/otn-pub/otn_software/jdbc/233/ucp11.jar
```

# 4. アプリケーション・コンティニュイティのDBサービス作成

アプリケーション・コンティニュイティを有効化したDBサービスを作成します。アプリケーション・コンティニュイティの各種オプションとロールベース・サービスを有効化します。下記マニュアルが参考になります。**アプリケーション・コンティニュイティはDBサービスの属性として機能するので、この属性を有効化したDBサービスを Data Guard のロールベース・サービスとして作るのが本記事の最大の要点です。**

> アプリケーション・コンティニュイティを使用するOracle RACのサービスの作成
> https://docs.oracle.com/cd/F19136_01/racad/ensuring-application-continuity.html#GUID-9DAE9270-A5BC-4A0F-9A55-D9DCFC0A9BF5
> 次のように、透過的アプリケーション・コンティニュイティを使用するサービスを作成できます。

下記はコマンドのサンプルとなります。Primary側BaseDB の oracleユーザーで実行して下さい。AYSDB19C_nmj_kix は Primary側CDB の DB_UNIQUE_NAME となります。-role で Primary側でのみ起動するDBサービスとします。

```shell
srvctl add service -db AYSDB19C_nmj_kix -service SRV_TAC_SERVICE -pdb AYSPDB19C -preferred AYSDB19C1,AYSDB19C2 \
 -failovertype AUTO -failover_restore AUTO -commit_outcome TRUE -replay_init_time 600 -retention 86400 \
 -notification TRUE -drain_timeout 300 -stopoption IMMEDIATE -role PRIMARY

srvctl config service -db AYSDB19C_nmj_kix -service SRV_TAC_SERVICE

srvctl start service -db AYSDB19C_nmj_kix -service SRV_TAC_SERVICE
```

OCI Console の Data Guard Association でスイッチオーバーしてスタンバイ側でもサービス追加します。
![ACwDG005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/1597536e-25fc-2d01-9d4f-647c9c63fd38.png)
![ACwDG006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/853dbbae-633d-865d-2f72-74c567aaa548.png)

下記はコマンドのサンプルとなります。Standby側BaseDB の oracleユーザーで実行して下さい。AYSDB19C_hck_kix は Standby側CDB の DB_UNIQUE_NAME となります。-role で Primary側でのみ起動するDBサービスとします。

```shell
srvctl add service -db AYSDB19C_hck_kix -service SRV_TAC_SERVICE -pdb AYSPDB19C -preferred AYSDB19C1,AYSDB19C2 \
 -failovertype AUTO -failover_restore AUTO -commit_outcome TRUE -replay_init_time 600 -retention 86400 \
 -notification TRUE -drain_timeout 300 -stopoption IMMEDIATE -role PRIMARY

srvctl config service -db AYSDB19C_hck_kix -service SRV_TAC_SERVICE

srvctl start service -db AYSDB19C_hck_kix -service SRV_TAC_SERVICE
```
下記は srvctl config service の実行結果サンプルとなります。

```shell
[oracle@aysoskdb19cracstb1 admin]$ srvctl config service -db AYSDB19C_hck_kix -service SRV_TAC_SERVICE
Service name: SRV_TAC_SERVICE
Server pool:
Cardinality: 2
Service role: PRIMARY
Management policy: AUTOMATIC
DTP transaction: false
AQ HA notifications: true
Global: false
Commit Outcome: true
Failover type: AUTO
Failover method:
Failover retries: 30
Failover delay: 10
Failover restore: AUTO
Connection Load Balancing Goal: LONG
Runtime Load Balancing Goal: NONE
TAF policy specification: NONE
Edition:
Pluggable database name: AYSPDB19C
Hub service:
Maximum lag time: ANY
SQL Translation Profile:
Retention: 86400 seconds
Replay Initiation Time: 600 seconds
Drain timeout: 300 seconds
Stop option: immediate
Session State Consistency: AUTO
GSM Flags: 0
Service is enabled
Preferred instances: AYSDB19C1,AYSDB19C2
Available instances:
CSS critical: no
[oracle@aysoskdb19cracstb1 admin]$
```

# 5. SQL*Plus で作成したDBサービスへの接続を確認

以下の接続文字列(簡易接続)で作成したサービスの接続を確認します。ポイントは以下の通りです。

* ADDRESS_LIST句 の記述で Primary → Standby の順序で接続を試みます(接続時フェイルオーバー)
* DESCRIPTION句 の RETRY_DELAY と RETRY_COUNT で Data Guard の Switchover/Failover時の接続不可時間帯を待機します。
* 接続不可時は上記の複合動作で Primary → Standby → Primary → Standby → ... の順序で接続を繰り返し試みます。
* SERVICE_NAME には上記4.で作成したロールベース・サービスを記述します。このDBサービスは Primary側でしか起動しないので、ネットワークエラー等で Standby側に誤接続する……という事はありません。

```sql
sqlplus /nolog
-- ※CONNECT文は実際には1行で記述
CONNECT AYSHIBAT/xxxxxxxx@(
  DESCRIPTION=
    (CONNECT_TIMEOUT=3)
    (TRANSPORT_CONNECT_TIMEOUT=3)
    (RETRY_DELAY=3)
    (RETRY_COUNT=20)
    (ENABLE=BROKEN)
    (ADDRESS_LIST=
      (LOAD_BALANCE=OFF)
      (FAILOVER=ON)
      (ADDRESS=(PROTOCOL=TCP)(HOST=aysoskdb19crac-scan.aysoskprvsubnet.aysoskvcn01.oraclevcn.com)(PORT=1521))
      (ADDRESS=(PROTOCOL=TCP)(HOST=aysoskdb19cracstb-scan.aysoskprvsubnet.aysoskvcn01.oraclevcn.com)(PORT=1521))
    )
    (CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=srv_tac_service.aysoskprvsubnet.aysoskvcn01.oraclevcn.com))
)
SET LINESIZE 170;
COLUMN HOST_NAME FORMAT A30;
SELECT INSTANCE_NUMBER, INSTANCE_NAME, HOST_NAME FROM GV$INSTANCE;
SELECT NAME, DB_UNIQUE_NAME, DATABASE_ROLE, OPEN_MODE FROM V$DATABASE;
```

下記は Primary に接続した際の実行結果サンプルです。

```sql
SQL> CONNECT AYSHIBAT/xxxxxxxx@(DESCRIPTION=(CONNECT_TIMEOUT=3)(TRANSPORT_CONNECT_TIMEOUT=3)(RETRY_DELAY=3)(RETRY_COUNT=20)(ENABLE=BROKEN)(ADDRESS_LIST=(LOAD_BALANCE=OFF)(FAILOVER=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=aysoskdb19crac-scan.aysoskprvsubnet.aysoskvcn01.oraclevcn.com)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=aysoskdb19cracstb-scan.aysoskprvsubnet.aysoskvcn01.oraclevcn.com)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=srv_tac_service.aysoskprvsubnet.aysoskvcn01.oraclevcn.com)))
Connected.
SQL> SET LINESIZE 170;
SQL> COLUMN HOST_NAME FORMAT A30;
SQL> SELECT INSTANCE_NUMBER, INSTANCE_NAME, HOST_NAME FROM GV$INSTANCE;

INSTANCE_NUMBER INSTANCE_NAME    HOST_NAME
--------------- ---------------- ------------------------------
              1 AYSDB19C1        aysoskdb19crac1
              2 AYSDB19C2        aysoskdb19crac2

SQL> SELECT NAME, DB_UNIQUE_NAME, DATABASE_ROLE, OPEN_MODE FROM V$DATABASE;

NAME      DB_UNIQUE_NAME                 DATABASE_ROLE    OPEN_MODE
--------- ------------------------------ ---------------- --------------------
AYSDB19C  AYSDB19C_nmj_kix               PRIMARY          READ WRITE

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

SYS_CONTEXT('USERENV','SERVICE_NAME')
------------------------------------------------------------
SRV_TAC_SERVICE.aysoskprvsubnet.aysoskvcn01.oraclevcn.com
```

下記は Standby側に Switchover(or Failover) した際の接続結果サンプルとなります。
HOST_NAME や DB_UNIQUE_NAME が変わっているのが確認できます。

```sql
SQL> CONNECT AYSHIBAT/xxxxxxxx@(DESCRIPTION=(CONNECT_TIMEOUT=3)(TRANSPORT_CONNECT_TIMEOUT=3)(RETRY_DELAY=3)(RETRY_COUNT=20)(ENABLE=BROKEN)(ADDRESS_LIST=(LOAD_BALANCE=OFF)(FAILOVER=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=aysoskdb19crac-scan.aysoskprvsubnet.aysoskvcn01.oraclevcn.com)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=aysoskdb19cracstb-scan.aysoskprvsubnet.aysoskvcn01.oraclevcn.com)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=srv_tac_service.aysoskprvsubnet.aysoskvcn01.oraclevcn.com)))
Connected.
SQL> SET LINESIZE 170;
SQL> COLUMN HOST_NAME FORMAT A30;
SQL> SELECT INSTANCE_NUMBER, INSTANCE_NAME, HOST_NAME FROM GV$INSTANCE;

INSTANCE_NUMBER INSTANCE_NAME    HOST_NAME
--------------- ---------------- ------------------------------
              1 AYSDB19C1        aysoskdb19cracstb1
              2 AYSDB19C2        aysoskdb19cracstb2

SQL> SELECT NAME, DB_UNIQUE_NAME, DATABASE_ROLE, OPEN_MODE FROM V$DATABASE;

NAME      DB_UNIQUE_NAME                 DATABASE_ROLE    OPEN_MODE
--------- ------------------------------ ---------------- --------------------
AYSDB19C  AYSDB19C_hck_kix               PRIMARY          READ WRITE

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

SYS_CONTEXT('USERENV','SERVICE_NAME')
------------------------------------------------------------
SRV_TAC_SERVICE.aysoskprvsubnet.aysoskvcn01.oraclevcn.com

SQL>
```

# 6. テーブルの作成

BaseDB の PDB にアプリケーション用ユーザーで接続してテスト用テーブルを作成しておきます。

```sql
CREATE TABLE AC_TEST_TABLE (
    C1 NUMBER
  , C2 VARCHAR2(100)
  , C3 DATE
);
```

# 7. Java + ucp.jar のサンプルプログラム

下記記事のものを流用しています。接続部分のみ異なるためそこをピックアップします。

https://qiita.com/ora_gonsuke777/items/5e348a4f444b2d3643d0

https://github.com/gonsuke777/OracleDatabase/blob/master/ac_java_ucp/AC_Sample.java

下記が変更した部分(DB_URL = 接続文字列)です。上記5. の SQL*Plus の接続文字列を流用しています。コメントにも記載しましたが実際には1行で記述して下さい。

```java
:
public class AC_UCPSample {
  // 実際には1行で記述します。
  final static String DB_URL = "jdbc:oracle:thin:@(
  DESCRIPTION=
    (CONNECT_TIMEOUT=3)
    (TRANSPORT_CONNECT_TIMEOUT=3)
    (RETRY_DELAY=3)
    (RETRY_COUNT=20)
    (ENABLE=BROKEN)
    (ADDRESS_LIST=
      (LOAD_BALANCE=OFF)
      (FAILOVER=ON)
      (ADDRESS=(PROTOCOL=TCP)(HOST=aysoskdb19crac-scan.aysoskprvsubnet.aysoskvcn01.oraclevcn.com)(PORT=1521))
      (ADDRESS=(PROTOCOL=TCP)(HOST=aysoskdb19cracstb-scan.aysoskprvsubnet.aysoskvcn01.oraclevcn.com)(PORT=1521))
    )
    (CONNECT_DATA=
      (SERVER=DEDICATED)
      (SERVICE_NAME=srv_tac_service.aysoskprvsubnet.aysoskvcn01.oraclevcn.com)
    )
  )";
:
```

# 8. サンプルプログラムのコンパイルと実行

まずはテーブルの件数確認

```sql
12:42:04 SQL> SELECT COUNT(*) FROM AC_TEST_TABLE;

  COUNT(*)
----------
         0

12:42:09 SQL>
```

下記がサンプルプログラムのコンパイルと実行のサンプルです。相変わらずの漢の生javac+生java実行
彡(ﾟ)(ﾟ)

```java
export JAVA_HOME=/home/opc/work/jdk-21.0.1
export PATH=${JAVA_HOME}/bin:${PATH}
export CLASSPATH=/home/opc/work/jdbc/ojdbc11.jar:/home/opc/work/jdbc/ucp11.jar:.
javac AC_UCPSample.java
java AC_UCPSample

[opc@ays-osk-prv-compute02-sandbox ac]$ java AC_UCPSample
Available connections before checkout: 0
Borrowed connections before checkout: 0
Available connections after checkout: 0
Borrowed connections after checkout: 1
Container Name - AYSPDB19C
Set AC Data start - 2023/12/06 12:43:25.391
1...2023/12/06 12:43:25.417
2...2023/12/06 12:43:26.449
3...2023/12/06 12:43:27.451
：
```

実行中に BaseDB を OCIコンソールから Switchover します。
![ACwDG006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/4d5117b4-3917-9894-3134-6e2a877d34de.png)

実行ログからは処理の中断が発生していることが確認できます。

```java
：
73...2023/12/06 12:44:37.572
74...2023/12/06 12:44:38.574
75...2023/12/06 12:44:39.576 ★ここで
76...2023/12/06 12:45:41.143 ★中断
77...2023/12/06 12:45:42.144
78...2023/12/06 12:45:43.146
：
98...2023/12/06 12:46:03.177
99...2023/12/06 12:46:04.178
100...2023/12/06 12:46:05.180
Set AC Data end   - 2023/12/06 12:46:06.186
Available connections after checkin: 1
Borrowed connections after checkin: 0
```

処理は最後まで動作しました。

```sql
12:48:29 SQL> SELECT COUNT(*) FROM AC_TEST_TABLE;

  COUNT(*)
----------
       100

12:48:30 SQL>
```

データも挿入されています。
彡(^)(^)

# 9. まとめ

Data Guard の Switchover で発生する使用不可時間を Application Continuity で吸収しつつトランザクションを続行できました。Data Guard によるローリング・パッチ適用(Standby-First Patch Apply)等でご活用下さいね。
彡(^)(^)

# Appendix. Application Continuity でトランザクション実行中のセッションを ALTER SYSTEM KILL SESSION ～ NOREPLAY で KILL してみる。

Oracle Database では ALTER SYSTEM KILL SESSION でセッションを強制切断できますが、そのオプションとして NOREPLAY を設定できるようになっています。

> SQL言語リファレンス - ALTER SYSTEM 
> https://docs.oracle.com/cd/F19136_01/sqlrf/ALTER-SYSTEM.html#GUID-2C638517-D73A-41CA-9D8E-A62D1A0B7ADB
> :
> NOREPLAY
> この句は、アプリケーション・コンティニュイティを使用している場合に有効です。アプリケーション・コンティニュイティが有効なサービスに接続しているとき(つまり、FAILOVER_TYPE = TRANSACTION)、セッションが失敗したり強制終了されると、セッションがリカバリされます。終了したセッションをリカバリする必要がない場合は、NOREPLAYを指定します

NOREPLAY句を付けるとアプリケーション・コンティニュイティによるトランザクション再実行を中断できます。サンプルプログラムのセッションをこの NOREPLAY句付きの KILL SESSION で切断してみます。

```sql
ALTER SYSTEM KILL SESSION '37,12800,@2' NOREPLAY;
```

(G)V$SESSION から SID, SERIAL#(RAC の場合は INST_NUMも)を調べて、上記のようにNOREPLAY句付きで KILL SESSION すると……

```java
：
18...2023/12/06 13:04:36.709
19...2023/12/06 13:04:37.710
20...2023/12/06 13:04:38.712
Dec 06, 2023 1:04:37 PM oracle.jdbc.replay.driver.TxnFailoverManagerImpl throwOriginalExceptionWithReplayError
WARNING: U:thread-33 UCP-worker-thread-2 On CONN$$$Proxy@5b367418, replay failed in method cancel, error code: 372, reason: java.sql.SQLException: ORA-17372: Replay is disabled because of a nonreplayable call: isUsable
https://docs.oracle.com/error-help/db/ora-17372/
Dec 06, 2023 1:04:37 PM oracle.jdbc.replay.driver.TxnFailoverManagerImpl throwOriginalExceptionWithReplayError
WARNING: U:thread-1 main On CONN$$$Proxy@5b367418, replay failed in method getAutoCommit, error code: 372, reason: java.sql.SQLException: ORA-17372: Replay is disabled because of a nonreplayable call: isUsable
https://docs.oracle.com/error-help/db/ora-17372/
java.sql.SQLException: ORA-00045: Your session has been terminated with no replay.

https://docs.oracle.com/error-help/db/ora-00045/
        at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:702)
        at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:608)
        at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1330)
        at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:1102)
        at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:456)
        at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:498)
        at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:272)
        at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1451)
        at oracle.jdbc.driver.OracleStatement.executeSQLStatement(OracleStatement.java:1958)
        at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1594)
        at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3754)
        at oracle.jdbc.driver.OraclePreparedStatement.executeLargeUpdate(OraclePreparedStatement.java:4100)
        at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:4071)
        at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:997)
        at oracle.jdbc.proxy.oracle$1jdbc$1replay$1driver$1TxnReplayableStatement$2oracle$1jdbc$1internal$1OraclePreparedStatement$$$Proxy.executeUpdate(Unknown Source)
        at oracle.ucp.jdbc.proxy.oracle$1ucp$1jdbc$1proxy$1oracle$1StatementProxy$2oracle$1jdbc$1internal$1OraclePreparedStatement$$$Proxy.executeUpdate(Unknown Source)
        at AC_UCPSample.SetACData(AC_UCPSample.java:103)
        at AC_UCPSample.main(AC_UCPSample.java:65)
Caused by: Error : 45, Position : 0, SQL = INSERT INTO AC_TEST_TABLE VALUES(:1 , :2 , SYSDATE), Original SQL = INSERT INTO AC_TEST_TABLE VALUES(?, ?, SYSDATE), Error Message = ORA-00045: Your session has been terminated with no replay.

        at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:710)
        ... 17 more
UCPSample - SQLException occurred : ORA-00045: Your session has been terminated with no replay.

https://docs.oracle.com/error-help/db/ora-00045/
Exception in thread "main" java.sql.SQLException: ORA-00045: Your session has been terminated with no replay.

https://docs.oracle.com/error-help/db/ora-00045/
        at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:702)
        at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:608)
        at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1330)
        at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:1102)
        at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:456)
        at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:498)
        at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:272)
        at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1451)
        at oracle.jdbc.driver.OracleStatement.executeSQLStatement(OracleStatement.java:1958)
        at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1594)
        at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3754)
        at oracle.jdbc.driver.OraclePreparedStatement.executeLargeUpdate(OraclePreparedStatement.java:4100)
        at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:4071)
        at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:997)
        at oracle.jdbc.proxy.oracle$1jdbc$1replay$1driver$1TxnReplayableStatement$2oracle$1jdbc$1internal$1OraclePreparedStatement$$$Proxy.executeUpdate(Unknown Source)
        at oracle.ucp.jdbc.proxy.oracle$1ucp$1jdbc$1proxy$1oracle$1StatementProxy$2oracle$1jdbc$1internal$1OraclePreparedStatement$$$Proxy.executeUpdate(Unknown Source)
        at AC_UCPSample.SetACData(AC_UCPSample.java:103)
        at AC_UCPSample.main(AC_UCPSample.java:65)
Caused by: Error : 45, Position : 0, SQL = INSERT INTO AC_TEST_TABLE VALUES(:1 , :2 , SYSDATE), Original SQL = INSERT INTO AC_TEST_TABLE VALUES(?, ?, SYSDATE), Error Message = ORA-00045: Your session has been terminated with no replay.

        at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:710)
        ... 17 more
：
```

上記のように ORA-17372エラー や ORA-00045エラーが発生して処理が中断しました。ちなみに NOREPLAY句無しで KILL SESSION すると再接続して処理は継続します。