Oracle RACを使用したアプリケーション・コンティニュイティのJava例 (2023/05/31)
Oracle RACを使用したアプリケーション・コンティニュイティのJava例 (2023/05/31)
https://database-heartbeat.com/2023/05/31/java-ac-rac/
はじめに
Oracle Application Continuity(アプリケーション・コンティニュイティ)は、データベースの中断をエンドユーザーやアプリケーションから隠します。SQL*Plusを使用した簡単なテストについては、このブログ記事で説明します。ただし、SQL*Plusは通常、本番で使用する実際のアプリケーションではありません。また、SQL*Plusはプールされたアプリケーションではなく、アプリケーション・コンティニュイティに接続プールを使用することをお薦めします。
このブログ投稿は、Oracle RACデータベースへのクイック・スタート接続のためのUniversal Connection Pool (UCP)を持つJDBCドライバを使用する単純なJavaの例を示しています。本番実装の推奨事項の完全なリストは、この投稿の最後にある公式のOracleドキュメントを参照してください。
環境
- Oracle Cloud上で稼働する2ノードのOracle RACデータベース・バージョン19.17
- Java JDK 11
- ローカルのWindows PC上のEclipse IDE for Java Developers
LinkedInポーリングでEclipseをお気に入りJava IDEとして最高レートを取得したため、ここでEclipseを使用しています。幸いにも私のお気に入りです。他のIDEでの構成はよく似ている必要があります。
データベース側
データベース・サービスの作成
次のようにカスタム・データベース・サービスを作成します。
[oracle@racnode1 ~]$ srvctl add service -db RACCDB_fra -pdb MOVIEDB -service acsrv -preferred RACCDB1,RACCDB2 -stopoption IMMEDIATE -replay_init_time 600 -retention 86400 -drain_timeout 10 -notification TRUE -commit_outcome TRUE -failover_restore LEVEL1 -failovertype TRANSACTION
[oracle@racnode1 ~]$ srvctl start service -db RACCDB_fra -service acsrv
[oracle@racnode1 ~]$ srvctl status service -db RACCDB_fra -service acsrv
Service acsrv is running on instance(s) RACCDB1,RACCDB2
アプリケーション・コンティニュイティは、-failover_restore LEVEL1 -failovertype TRANSACTIONによって有効になります。
データベース・ユーザーの作成
ユーザーおよびテスト用の単純な表を作成します。
[oracle@racnode1 ~]$ sqlplus /
as
sysdba
SQL>
alter
session
set
container=moviedb;
Session altered.
SQL>
create
user
acusr identified
by
VerySecretPW__2023 quota unlimited
on
users;
User
created.
SQL>
grant
connect
to
acusr;
Grant
succeeded.
SQL>
create
table
acusr.actab (text varchar2(128));
Table
created.
高速アプリケーション通知(FAN)の有効化
FANポート(通常は6200)は、データベース側で開く必要があります。
クライアント側では、推奨される接続文字列を使用すると、FANはGrid Infrastructure 12c、Oracle Database 12cおよびOracle Client 12c以降から自動構成されます。次を参照してください。
クライアント側
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)を作成します。
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=C:\\Users\\SPETRUS\\Documents\\spetrus\\development
tns_alias=acsrv
db_user=acusr
db_password=VerySecretPW__2023
テストでは、プロパティ・ファイルを使用するのではなく、値をコードに直接配置することもできます。
接続文字列
TNS_ADMINディレクトリのtnsnames.oraファイルで、次の推奨される接続文字列を使用します。
ACSRV = (DESCRIPTION =
(CONNECT_TIMEOUT=90)(RETRY_COUNT=50)(RETRY_DELAY=3)(TRANSPORT_CONNECT_TIMEOUT=3)
(ADDRESS_LIST =
(LOAD_BALANCE=ON)
(ADDRESS = (PROTOCOL = TCP)(HOST=racnode-scan.subnetpublic.vcnfra.oraclevcn.com)(PORT=1521)))
(CONNECT_DATA=(SERVICE_NAME = acsrv.subnetpublic.vcnfra.oraclevcn.com)))
SCANがクライアントから解決できず、テストにパブリック・ホストIPを使用している場合は、ADDRESS_LISTに別のADRESSを追加します:
ACSRV = (DESCRIPTION =
(CONNECT_TIMEOUT=90)(RETRY_COUNT=50)(RETRY_DELAY=3)(TRANSPORT_CONNECT_TIMEOUT=3)
(ADDRESS_LIST =
(LOAD_BALANCE=ON)
(ADDRESS = (PROTOCOL = TCP)(HOST = 130.61.216.103)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = 130.61.217.251)(PORT = 1521)))
(CONNECT_DATA=(SERVER = DEDICATED)(SERVICE_NAME = acsrv.subnetpublic.vcnfra.oraclevcn.com)))
テスト時間
コミットが実行される前とリクエストの終了前に、2つのブレーク・ポイントを設定します。
デバッグ・モードで実行:
コミットが実行される前にプログラムが停止します。
この時点で、データベースにログインし、ユーザーACUSRの既存のセッションを問い合せます。
set
lines 300
col username
for
a10
col service_name
for
a20
SQL>
select
username, sid, serial#, inst_id, service_name
from
gv$session
where
username =
'ACUSR'
;
ユーザーはインスタンス#1に接続しています:
次に、インスタンス#1でサービスを停止します:
[oracle@racnode1 ~]$ srvctl stop service -db RACCDB_fra -service acsrv -instance RACCDB1 -drain_timeout 10
[oracle@racnode1 ~]$ srvctl status service -db RACCDB_fra -service acsrv
サービスで指定されたドレイン・タイムアウト(この場合は10秒)が経過するまで待機し、gv$sessionを再度問い合せます:
Eclipseに戻り、実行を再開します。
実行は続行され、次のブレーク・ポイントで停止します。
最も重要なことは、サービスが停止したにもかかわらず、アプリケーションはエラー・メッセージを表示せずに継続したことです。
gv$sessionを問い合せるデータベースに戻ると、ユーザーがインスタンス#2に接続されたことがわかります。
アプリケーションを中断せずにコミットが正常に完了しました:
まとめ
Oracle Application Continuityは、使用可能なデータベース・インスタンス上で処理中のトランザクションをリプレイすることで、エンド・ユーザーからデータベースの中断を隠します。エンド・ユーザーに対しては完全に透過的で、アプリケーション・コードの変更は不要です。
提供されているJavaコードは、JavaでOracle Application Continuityの使用を開始する例です。本番実装の場合は、Oracleのドキュメントに記載されている手順と推奨事項に従ってください。
追加情報
- Application Continuity for Java – JDBC Developer’s Guide
- Ensuring Application Continuity – Universal Connection Pool Developer’s Guide
- Application Checklist for Continuous Service with Autonomous Database on Shared Infrastructure
- Best Practices for Applications Using Autonomous Database – Dedicated
- Application Checklist for Continuous Service for MAA Solutions
- Best Practices for Adopting Transparent Application Continuity
- Application Continuity for the Oracle Database
- Oracle JDBC Drivers – What JDBC driver version to choose
コメント
コメントを投稿