JDBC Oracle Connection Poolingのいくつかのアイテムを調査していて、ユニバーサル接続プール(UCP)と呼ばれる新しい(新しい)Oracle Pool実装に出会いました。これで、OracleDataSource [キャッシュオプションを有効化]ではなく、接続プーリングに新しいクラスPoolDataSourceを使用します。この新しい実装に切り替えるかどうかを議論していますが、(もしあれば)修正/アップグレードすることで得られる良いドキュメントが見つかりません。誰もが両方の経験がありますか?プラス/マイナス?ありがとう。
最新のOracle jdbcドライバー(11.2.0.1.0)は、Oracle Implicit Connectionキャッシュ(OracleDataSourceを使用するキャッシュ)が非推奨であると明示しています:
Oracle JDBCドライバーリリース11.2.0.1.0製品版Readme.txt
このリリースの新機能
ユニバーサル接続プールこのリリースでは、Oracle Implicit Connection Cache機能は廃止されています。代わりに、新しいユニバーサル接続プールを使用することを強くお勧めします。 UCPには、ICCのすべての機能に加えて、さらに多くの機能があります。 UCPは、別個のjarファイルucp.jarで利用可能です。
したがって、UCPを使い始める方が良いと思いますが、ドキュメントはそれほど良くありません。たとえば、春にUCPを使用する方法が見つかりませんでした...
PDATE:正しいスプリング構成を見つけました:OK正しい構成を見つけたと思います:
<bean id="dataSource" class="Oracle.ucp.jdbc.PoolDataSourceFactory" factory-method="getPoolDataSource">
<property name="URL" value="jdbc:Oracle:thin:@myserver:1521:mysid" />
<property name="user" value="myuser" />
<property name="password" value="mypassword" />
<property name="connectionFactoryClassName" value="Oracle.jdbc.pool.OracleDataSource" />
<property name="connectionPoolName" value="ANAG_POOL" />
<property name="minPoolSize" value="5" />
<property name="maxPoolSize" value="10" />
<property name="initialPoolSize" value="5" />
<property name="inactiveConnectionTimeout" value="120" />
<property name="validateConnectionOnBorrow" value="true" />
<property name="maxStatements" value="10" />
</bean>
重要なのは、適切なファクトリクラスと適切なファクトリメソッドを指定することです。
PDSは、「Oracle」以外のデータベースに対してODSで取得するのと同じレベルのプーリング機能を提供するため、「ユニバーサル」です。 MySQL。
CP開発ガイド 、 Oracle Webサイトの記事 および CP移行ガイド を参照してください
ODSからUCP(PDS)に移行することの直接的な利点はありませんが、将来的にはOracleはODSの機能の一部を廃止する可能性があります。私はしばらくの間ODSを使用しましたが、当面の間はかなり満足していますが、新しく始めた場合はPDSを使用します。
私はUCPの広範な評価を行い、UCPを使用しないことにしました- 詳細については、この投稿をご覧ください 。
UCPをテストし、Spring JMSリスナーコンテナと、@ Transactionalアノテーションを使用したSpring管理のセッションとトランザクションを使用して、Spring 3.0.5 HibernateアプリのプロダクションにUCPをデプロイしました。別のリスナースレッドが同じレコードを更新しようとするため、データによってSQL制約エラーが発生する場合があります。その場合、@ Transactionalアノテーションが付けられた1つのメソッドによって例外がスローされ、@ Transactionalアノテーションが付けられた別のメソッドを使用してデータベースにエラーが記録されます。なんらかの理由で、このプロセスによりカーソルリークが発生し、最終的にORA-01000のオープンカーソル制限超過エラーが発生し、スレッドの処理が停止します。
同じコードで実行されているOracleDataSourceはカーソルをリークしないように見えるため、この問題は発生しません。
これはかなり奇妙なシナリオですが、この種の構造を持つアプリケーションでUCPを使用するには少し早すぎることを示しています。
私もUCPをテストしていますが、スレッドプールベースのアプリケーションでパフォーマンスの問題が発生していることに気付きました。最初は、OracleDataSourceを試しましたが、バッチ処理用に構成するのに問題があります。接続でNullPointerExceptionsを取得し続けるため、何らかの接続リークがあると思われますが、一部のアプリケーションでのみ、OracleDataSourceがうまく機能するバッチプロセス指向ではない他のアプリケーションが管理されています。
この投稿と私がこの主題の研究を見つけた他のいくつかに基づいて、UCPを試しました。十分な調整を行うと、接続スタイルエラーで閉じられた接続/ NullPointerExceptionsを取り除くことができることがわかりましたが、ガベージコレクションは打撃を受けていました。長期GCはすぐにいっぱいになり、アプリケーションの実行が完了するまで解放されないようです。負荷が本当に重い場合、これには1日以上かかることがあります。また、データを処理するのに累進的に時間がかかることにも気付きました。 UCPがファイルをより速く処理し、処理するGCメモリの3分の1を使用した、現在は減価償却されているOracleCacheImplクラス(現在も運用で使用されている)と比較します。他のすべてのアプリケーションでは、UCPは問題なく動作し、私が投げるほぼすべてを処理しますが、スレッドプールアプリケーションは主要なアプリケーションであり、実稼働中のGC例外のリスクはありません。
接続検証を使用する場合、暗黙的な接続キャッシュはUCPよりもかなり優れたパフォーマンスを発揮します。これはバグ16723836に対応しており、12.1.0.2で修正される予定です。
UCPプーリングは、同時負荷が増加するにつれて、接続を取得/返すためのコストがますます高くなります。このテストでは、Oracleの暗黙的な接続キャッシュ、Tomcatのプーリング、およびUCPを比較します。 3つすべては、最大200接続、最小20接続、および初期サイズ2を許可するように構成されています。3つすべては、プールから削除される接続を検証するように構成されています。 Tomcatプールは、検証にステートメント「select sysdate from dual」を使用します。
これらの結果は、64個の論理コア(32個の物理)と128 GBのRAMを備えた64ビットRedHatノードで発生します。
5つの同時スレッドでは、UCPが最も遅くなりますが、合計接続管理時間(getおよびclose)は平均で1ミリ秒未満です。同時実行性が向上すると、UCPは他のソリューションよりもさらに遅れをとります。
25 Threads:
Implicit: 0.58ms
Tomcat: 0.92ms
UCP: 1.50ms
50 Threads:
Implicit: 0.92ms
Tomcat: 1.60ms
UCP: 6.80ms
100 Threads:
Implicit: 2.60ms
Tomcat: 3.20ms
UCP: 21.40ms
180 Threads:
Implicit: 13.86ms
Tomcat: 15.34ms
UCP: 40.70ms
Spring Bean.xmlでUCPを使用する方法は2つあります。
ファイルによって設定されたdb.propertiesの場合、これをロードしてから、それらのいずれかを使用します。
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:resources/db.properties</value>
</property>
</bean>
Oracle.ucp.jdbc.PoolDataSourceImplを使用した最初の1つ:
<bean id="dataSource" class="Oracle.ucp.jdbc.PoolDataSourceImpl">
<property name="URL" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="validateConnectionOnBorrow" value="true"/>
<property name="connectionFactoryClassName" value="Oracle.jdbc.pool.OracleDataSource" />
<property name="connectionPoolName" value="TEST_POOL" />
<property name="minPoolSize" value="10" />
<property name="maxPoolSize" value="20" />
<property name="initialPoolSize" value="12" />
</bean>
Oracle.ucp.jdbc.PoolDataSourceFactoryを使用した2つ目:-
<bean id="dataSource" class="Oracle.ucp.jdbc.PoolDataSourceFactory"
factory-method="getPoolDataSource">
<property name="URL" value="${jdbc.url}" />
<property name="user" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="validateConnectionOnBorrow" value="true"/>
<property name="connectionFactoryClassName" value="Oracle.jdbc.pool.OracleDataSource" />
<property name="connectionPoolName" value="TEST_POOL" />
<property name="minPoolSize" value="10" />
<property name="maxPoolSize" value="20" />
<property name="initialPoolSize" value="12" />
</bean>
それだけです:)詳細なドキュメントのリンクは次のとおりです。 https://docs.Oracle.com/cd/E11882_01/Java.112/e12265/connect.htm#CHDDCICA
私はUCPを試しましたが、パフォーマンスは向上しています...キーがこれを使用している可能性があります
Oracle.ucp.jdbc.PoolDataSource ds = (Oracle.ucp.jdbc.PoolDataSource)envContext.lookup(url_r);
MyConnectionLabelingCallback callback = new MyConnectionLabelingCallback();
ds.registerConnectionLabelingCallback( callback );
Properties label = new Properties();
label.setProperty(pname, KEY);
conn = ds.getConnection(label);
これは、接続を借用し、決して閉じないようにするのに役立ちます。したがって、パフォーマンスは優れています
コールバッククラスのコードは
public class MyConnectionLabelingCallback
implements ConnectionLabelingCallback {
public MyConnectionLabelingCallback()
{
}
public int cost(Properties reqLabels, Properties currentLabels)
{
// Case 1: exact match
if (reqLabels.equals(currentLabels))
{
System.out.println("## Exact match found!! ##");
return 0;
}
// Case 2: some labels match with no unmatched labels
String iso1 = (String) reqLabels.get("TRANSACTION_ISOLATION");
String iso2 = (String) currentLabels.get("TRANSACTION_ISOLATION");
boolean match =
(iso1 != null && iso2 != null && iso1.equalsIgnoreCase(iso2));
Set rKeys = reqLabels.keySet();
Set cKeys = currentLabels.keySet();
if (match && rKeys.containsAll(cKeys))
{
System.out.println("## Partial match found!! ##");
return 10;
}
// No label matches to application's preference.
// Do not choose this connection.
System.out.println("## No match found!! ##");
return Integer.MAX_VALUE;
}
public boolean configure(Properties reqLabels, Object conn)
{
System.out.println("Configure################");
try
{
String isoStr = (String) reqLabels.get("TRANSACTION_ISOLATION");
((Connection)conn).setTransactionIsolation(Integer.valueOf(isoStr));
LabelableConnection lconn = (LabelableConnection) conn;
// Find the unmatched labels on this connection
Properties unmatchedLabels =
lconn.getUnmatchedConnectionLabels(reqLabels);
// Apply each label <key,value> in unmatchedLabels to conn
for (Map.Entry<Object, Object> label : unmatchedLabels.entrySet())
{
String key = (String) label.getKey();
String value = (String) label.getValue();
lconn.applyConnectionLabel(key, value);
}
}
catch (Exception exc)
{
return false;
}
return true;
}
}