Autonomous DatabaseでのOracle Application ContinuityのJava例 (2023/08/22)

Autonomous DatabaseでのOracle Application ContinuityのJava例 (2023/08/22)

https://database-heartbeat.com/2023/08/22/java-ac-adb/




はじめに


Oracle Application Continuityは、データベースの中断をエンド・ユーザーおよびアプリケーションから隠します。このブログ投稿では、SQL*Plusを使用した簡単なテストについて説明します。ただし、SQL*Plusは通常、本番で使用する実際のアプリケーションではありません。また、SQL*Plusはプールされたアプリケーションではなく、アプリケーション・コンティニュイティに接続プールを使用することをお薦めします。


このブログ投稿は、Oracle Autonomous Databaseへのクイック・スタートのためのユニバーサル接続プール(UCP)を持つJDBCドライバを使用する単純なJavaの例を示しています。本番実装の推奨事項の完全なリストは、この投稿の最後にある公式のOracleドキュメントを参照してください。



環境


  • Oracle Cloudで実行されているAlways FreeのOracle Autonomous Database
  • Java JDK 11
  • ローカルのWindows PC上のEclipse IDE for Java Developers


データベース側


専用Exadataインフラストラクチャ上のAutonomous Databaseでは、事前定義されたサービスtp_tls、tp、tpurgent_tlsおよびtpurgentに対して、透過的アプリケーション・コンティニュイティがデフォルトで有効になっています。これらのサービスを使用している場合、データベース側でこれ以上のアクションは必要ありません。


ADMINとして接続


ADMINユーザーとしてAutonomous Databaseに接続します。たとえば、Database Actionsの「SQL」タブを使用します:



アプリケーション・コンティニュイティの有効化


Oracle Autonomous Databaseには、事前定義されたデータベース・サービスがあります。アプリケーションで使用されるサービスのアプリケーション・コンティニュイティを有効にします。


SQL> execute DBMS_APP_CONT_ADMIN.ENABLE_AC('lmdzfmg7spyxoty_adbfree_high.adb.oraclecloud.com', 'LEVEL1', 1200);
PL/SQL procedure successfully completed.
 
SQL> exec DBMS_APP_CONT_ADMIN.SET_DRAINING('lmdzfmg7spyxoty_adbfree_high.adb.oraclecloud.com', 10, 'IMMEDIATE');
PL/SQL procedure successfully completed.
 
SQL> select name, failover_type, stop_option, drain_timeout from dba_services where lower(name) = lower('lmdzfmg7spyxoty_adbfree_high.adb.oraclecloud.com');
NAME                                               FAILOVER_TYPE   STOP_OPTION     DRAIN_TIMEOUT
-------------------------------------------------- --------------- --------------- -------------
LMDZFMG7SPYXOTY_ADBFREE_high.adb.oraclecloud.com   LEVEL1          IMMEDIATE                  10


データベース・ユーザーの作成


ユーザーおよびテスト用の単純な表を作成します。


SQL> create user acusr identified by VerySecretPW__2023 quota unlimited on data;
User created.
 
SQL> grant dwrole to acusr;
Grant succeeded.
 
SQL> create table acusr.actab (text varchar2(128));
Table created.


クライアント側

Autonomous Clientの資格証明


クライアント資格証明(.zipウォレット・ファイル)をダウンロードして、クライアント・マシン(この場合はC:\Users\SPETRUS\Documents\spetrus\development\ADB_wallets\ADBFREEディレクトリ)で解凍します。


次のディレクトリを指すように、sqlnet.oraのWALLET_LOCATIONディレクトリを設定します。

WALLET_LOCATION = (SOURCE = (METHOD = file) (METHOD_DATA = (DIRECTORY="C:\Users\SPETRUS\Documents\spetrus\development\ADB_wallets\ADBFREE")))
SSL_SERVER_DN_MATCH=yes


JDKのインストール


常にJavaを使用している場合は、JDKがすでに使用されているはずです。Javaを初めて使用する場合:


Windowsの場合は、ここで説明するようにインストールに従います。


Linuxの場合は、インストールガイドに従うか、yumを使用できます。

sudo yum install java-11-openjdk


Eclipse IDE for Javaのインストール


お気に入りではなく、試してみたい場合は、こちらからダウンロードできます。


Windowsの場合は、インストール手順に従います。


Linuxの場合、バイナリを解凍して実行します。

tar -zxvf eclipse-java-2022-12-R-linux-gtk-x86_64.tar.gz
chmod 744 eclipse
./eclipse


JDBCおよびUCP .jarライブラリのダウンロード


JDBCおよびUCPのダウンロード・ページから、圧縮されたJDBCドライバ(ojdbc11.jar)およびコンパニオンJarsファイルojdbc11-full.tar.gzをダウンロードします。


zipファイルを抽出し、次のJARファイルをアプリケーションのCLASSPATHに追加します。


  • ons.jar、ojdbc11.jarおよびucp11.jar


Eclipseで、プロジェクト名を右クリックし、「Build Path」、「Configure Build Path...」の順にクリックします。



「Libraries、 Classpath」を選択し、「Add External Jars...」をクリックし、zipファイルを抽出するディレクトリから前述の.jarファイルを選択し、「Apply and Close」をクリックします。





Javaの例


次のコード例を使用して、新しいJavaクラス(AC.java)を作成します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Statement;
import java.util.Properties;
 
//PoolDataSource
import oracle.jdbc.OracleConnection;
import oracle.ucp.jdbc.PoolDataSourceFactory;
import oracle.ucp.jdbc.PoolDataSource;
 
public class AC {
 
    public static void main(String[] args) {
        usePoolDataSource();
    }
     
    public static void usePoolDataSource() {
        try {          
            //use Universal Connection Pool (UCP)
            PoolDataSource pds = PoolDataSourceFactory.getPoolDataSource();
            pds.setConnectionFactoryClassName("oracle.jdbc.datasource.impl.OracleDataSource");
            pds.setConnectionPoolName("JDBC_UCP");
            //pds.setInitialPoolSize(10);
            pds.setMinPoolSize(4);
            pds.setMaxPoolSize(20);
             
            //load properties
            String PROP_FILE = "C:\Users\SPETRUS\Documents\spetrus\development\java\ACproject\src\config.properties";
            InputStream propInput = new FileInputStream(PROP_FILE);
            Properties prop = new Properties();
            prop.load(propInput);
             
            //set properties
            System.setProperty("oracle.net.tns_admin", prop.getProperty("tns_admin"));
            pds.setURL("jdbc:oracle:thin:@"+prop.getProperty("tns_alias"));
            pds.setUser(prop.getProperty("db_user"));
            pds.setPassword(prop.getProperty("db_password"));
             
            //enable FAN and connection tests
            pds.setConnectionWaitTimeout(3);
            pds.setFastConnectionFailoverEnabled(true);
            pds.setValidateConnectionOnBorrow(true);
             
            //disable auto-commit
            pds.setConnectionProperty(OracleConnection.CONNECTION_PROPERTY_AUTOCOMMIT, "false");
            pds.setConnectionProperty(OracleConnection.CONNECTION_PROPERTY_IMPLICIT_STATEMENT_CACHE_SIZE, "100");
             
            //get connection from the pool
            Connection conn = pds.getConnection();
            //conn.beginRequest(); //not needed, as connection pool sets explicit begin request boundary at getConnection()
            conn.setAutoCommit(false);
             
            //execute query
            Statement stmt = conn.createStatement();                               
            String insert = "insert into acusr.actab values ('Using Application Continuity')";
            int result = stmt.executeUpdate(insert);
            System.out.println("insert result is: " + result); 
            //stop here in bedug mode & (relocate | switchover | terminate the session)
            conn.commit();
            //conn.endRequest(); //not needed, as connection pool sets explicit end request boundary at close()
            conn.close();
            conn=null;         
        }
        catch (Exception e) {
            e.printStackTrace();
        
    }
}


この場合、config.propertiesファイルには、次の値が含まれます。

tns_admin=tns_admin=C:\\Users\\SPETRUS\\Documents\\spetrus\\development\\ADB_wallets\\ADBFREE
tns_alias=adbfree_high
db_user=acusr
db_password=VerySecretPW__2023


テストでは、プロパティ・ファイルを使用するのではなく、値をコードに直接配置することもできます。



テスト


コミットが実行される前とリクエストの終了前に、2つのブレーク・ポイントを設定します。



デバッグ・モードで実行:



コミットが実行される前にプログラムが停止します。



この時点で、データベースにログインし、ユーザーACUSRの既存のセッションを問い合せます。

set lines 300
col username for a10
col service_name for a60
SQL> select username, sid, serial#, inst_id, service_name from gv$session where username = 'ACUSR';


SID、SERIAL#およびINST_IDを書き留めます。



このセッションを終了します。

SQL> alter system kill session '43106,61951,@2';
System altered.


gv$sessionを再度問い合せます。



Eclipseに戻り、実行を再開します。

https://databaseheartbeat.files.wordpress.com/2023/03/20230317_155524.jpg

実行は続行され、次のブレーク・ポイントで停止します。


最も重要なことは、セッションが途中で終了したにもかかわらず、アプリケーションはエラー・メッセージを表示せずに続行することです。



gv$sessionを問い合せるデータベースに戻ると、ユーザーが別のセッションを介して接続されたことがわかります。


アプリケーションを中断せずにコミットが正常に完了しました:





まとめ


Oracle Application Continuityは、使用可能なデータベース・インスタンス上で処理中のトランザクションをリプレイすることで、エンド・ユーザーからデータベースの中断を隠します。エンド・ユーザーに対しては完全に透過的で、アプリケーション・コードの変更は不要です。


提供されているJavaコードは、JavaでOracle Application Continuityの使用を開始する例です。本番実装の場合は、Oracleが提供する手順および推奨事項に従ってください。


参考情報

コメント

このブログの人気の投稿

Oracle Database 19cサポート・タイムラインの重要な更新 (2024/11/20)

ミリ秒の問題: BCCグループとOCIが市場データ・パフォーマンスを再定義する方法(AWSに対するベンチマークを使用) (2025/11/13)

Oracle DatabaseをOCI Object Storageの不変バケットにバックアップする理由と方法 (2024/05/27)