ヘッダーをスキップ
Oracle® Coherence開発者ガイド
リリース3.6.1
B61368-02
  ドキュメント・ライブラリへ移動
ライブラリ
製品リストへ移動
製品
目次へ移動
目次

前
 
次
 

25 トランザクションの実行

この章では、Coherenceのトランザクションとデータの同時実行性機能の使用手順について説明します。ユーザーは、この章を読む前に、トランザクションの原則を理解しておいてください。また、Coherenceリソース・アダプタには、J2EE Connector Architecture(J2CA)、Java Transaction API(JTA)およびJava EEデプロイメントの知識が必要です。

この章は次の各項で構成されています。

トランザクションの概要

トランザクションは、プログラマが多数の状態変更のスコープを1つの作業ユニットに設定できるようにして、状態変更が発生する正しい成果がシステム内で得られるようにします。状態変更は、障害が発生しないで各変更が完了できる場合にのみコミットされます。それ以外の場合には、すべての変更は前回の状態にロールバックされる必要があります。

トランザクションは、通常ACIDプロパティ(原子性(Atomicity)、一貫性(Consistency)、独立性(Isolation)、永続性(Durability))と呼称される一連の条件を保持しようとします。

ACIDプロパティは、トランザクションのインフラストラクチャだけでは保持できず、カスタマイズされたビジネス・ロジックが必要となることがあります。たとえば、一貫性プロパティには、システムの変更が有効か無効かを確認するプログラム・ロジックが必要です。また、ACIDプロパティを厳格に遵守すると、インフラストラクチャとアプリケーションのパフォーマンスに直接影響を与えることがあるため、慎重に検討する必要があります。

Coherenceには、様々なトランザクションの保証が得られる各種のトランザクション・オプションが用意されています。このオプションは、アプリケーションやソリューションのトランザクション要件に応じて選択する必要があります。

表25-1は、Coherenceに用意されている各種トランザクション・オプションをまとめたものです。

表25-1 Coherenceのトランザクション・オプション

オプション名 説明

明示的ロック

ConcurrentMapインタフェース(NamedCacheインタフェースによって拡張されている)は、明示的ロック操作をサポートします。ロックAPIはデータの同時実行性を保証しますが、原子性は保証しません。このオプションの詳細は、「データの同時実行性のための明示的ロックの使用方法」を参照してください。

入力プロセッサ

Coherenceは、EntryProcessor APIによるロックなしのプログラミング・モデルもサポートしています。多くのトランザクション・タイプでは、これにより競合や待機時間が最小限に抑えられ、データ操作のフォルト・トレランスを犠牲にすることなく、システム・スループットを向上させます。このオプションでは、高レベルの同時実行性は制御されますが、原子性は保証されていません。このオプションの詳細は、「データの同時実行性のための入力プロセッサの使用方法」を参照してください。

トランザクション・フレームワークAPI

Coherenceトランザクション・フレームワークAPIは接続ベースのAPIで、これにより、クライアントに障害が発生した場合でも、パーティションおよびキャッシュ全体にわたって原子性トランザクションが保証されます。このフレームワークは、NamedCache操作、問合せ、集計、およびトランザクションのコンテキスト内の入力プロセッサの使用をサポートします。このオプションの詳細は、「トランザクション・フレームワークAPIの使用方法」を参照してください。

Coherenceリソース・アダプタ

Coherenceリソース・アダプタが、Coherenceトランザクション・フレームワークAPIを利用することにより、Coherenceはリソースとして、JavaEEコンテナのトランザクション・マネージャで管理されるXAトランザクションに参加できます。このトランザクション・オプションにより、原子性の保証が実現します。このオプションの詳細は、「Coherenceリソース・アダプタの使用方法」を参照してください。


データの同時実行性のための明示的ロックの使用方法

標準的なNamedCacheインタフェースは、基本的なロック・メソッドを含むConcurrentMapインタフェースを拡張します。ロック操作は、エントリ・レベルで、NamedCache内の特定のキーに対してロックをリクエストすることで適用されます。

例25-1 キャッシュでのロック操作の適用

...
NamedCache cache = CacheFactory.getCache("dist-cache");
Object key = "example_key";
cache.lock(key, -1);
try
    {
    Object value = cache.get(key);
    // application logic
    cache.put(key, value);
    }
finally
    {
    // Always unlock in a "finally" block
    // to ensure that uncaught exceptions
    // don't leave data locked
    cache.unlock(key);
    }
...

Coherenceのロック機能では、JavaのsynchronizedキーワードおよびC#のlockキーワードと同様、ブロック・ロックのみをロックします。複数のスレッドが共同で、ロックを適切に使用してデータへのアクセスを調整する必要があります。スレッドが、ある項目のキーをロックしていても、別のスレッドはロックせずにその項目を読み取ることができます。

ロックはサーバー障害の影響を受けず、バックアップ・サーバーにフェイルオーバーします。ロック所有者(クライアント)に障害が発生すると、ロックはただちに解除されます。

ロックの動作は、リクエストされたタイムアウトとキャッシュのタイプに応じて異なります。タイムアウトが-1の場合はロックを取得できるまで無限にブロックされ、0の場合はただちに返され、0より大きい値の場合は指定した時間(ミリ秒単位)待機してからタイムアウトします。コール元が実際にロックを取得したことを確認するには、返されたブール値を調べる必要があります。詳細は、ConcurrentMap.lock()を参照してください。タイムアウト値がlock()に渡されない場合、デフォルトは0になります。レプリケーション・キャッシュでは、ConcurrentMap.LOCK_ALLをキーとして使用してキャッシュ全体をロックできますが、通常はお薦めしません。この操作は、パーティション・キャッシュではサポートされていません。

レプリケーション・キャッシュとパーティション・キャッシュの両方で、getはロックされているキーで許可されます。putは、レプリケーション・キャッシュではブロックされますが、パーティション・キャッシュではブロックされません。ロックが行われている場合、ロックの解放はコール元の責任です(lease-granularityの構成によって、同じスレッド内または同じクラスタ・ノード内で実行される)。このような理由から、ロックは常にfinally句(または同等のもの)で解放する必要があります。そうでない場合、未処理の例外があると無限にロックされることがあります。lease-granularity構成の詳細は、「DistributedCacheサービスのパラメータ」を参照してください。

データの同時実行性のための入力プロセッサの使用方法

NamedCacheのスーパーインタフェースであるInvocableMapを使用すると、キャッシュ内で処理コードをロックなしで同時に実行できます。この処理は、EntryProcessorによって実行されます。EntryProcessorsは、より一般的なConcurrentMapの明示的ロックAPIに比べて柔軟性が少ないかわりに、データの信頼性を犠牲にすることなく最高レベルの効率を提供します。

EntryProcessorsは、処理中のエントリに対して暗黙的な低レベルのロックをかけるため、エンド・ユーザーは、EntryProcessorに処理コードを配置する際に並列処理制御に煩わされずに済みます。これは、ConcurrentMap APIで提供されている明示的なlock(key)機能とは異なります。

Caching Editionで動作しているレプリケーション・キャッシュやパーティション・キャッシュでは、開始クライアントでローカルに実行されます。Enterprise Edition以上で動作しているパーティション・キャッシュでは、データのプライマリ・ストレージを提供するノードで実行されます。

InvocableMapでは、次の3つの方法でEntryProcessorを起動できます。

Enterprise Edition以上で動作しているパーティション・キャッシュでは、EntryProcessorsは、クラスタ全体で並列実行されます(個々のエントリを所有するノード上で)。これは、クライアントで影響を受けるキーをすべてロックし、キャッシュから必要なデータをすべて取得した後、データを処理してキャッシュにデータを戻してからキーをロック解除するのに比べて大きな利点があります。この処理は、1台のマシンで順次実行されるかわりに、複数のマシンで並列実行されるため、ロックの獲得や解放に伴うネットワークのオーバーヘッドがなくなります。


注意:

各クラスタ・ノードのクラスパスでEntryProcessorクラスを使用できる必要があります。

高レベルの並列処理制御のサンプルは次のとおりです。ネットワーク・アクセスが必要なコードにはコメントが付いています。

例25-2 EntryProcessorを使用しない並列処理制御

final NamedCache cache = CacheFactory.getCache("dist-test");
final String key = "key";

cache.put(key, new Integer(1));


// begin processing

// *requires network access*
if (cache.lock(key, 0))
    {
    try
        {
        // *requires network access*
        Integer i = (Integer) cache.get(key);
        // *requires network access*
        cache.put(key, new Integer(i.intValue() + 1));
        }
    finally
        {
        // *requires network access*
        cache.unlock(key);
        }
    }

// end processing

次に、EntryProcessorを使用した同等の方法を示します。ここでも、ネットワーク・アクセスにはコメントが付いています。

例25-3 EntryProcessorを使用する並列処理制御

final NamedCache cache = CacheFactory.getCache("dist-test");
final String key = "key";

cache.put(key, new Integer(1));


// begin processing

// *requires network access*
cache.invoke(key, new MyCounterProcessor());

// end processing

...

public static class MyCounterProcessor
        extends AbstractProcessor
    {
    // this is executed on the node that owns the data,
    // no network access required
    public Object process(InvocableMap.Entry entry)
        {
        Integer i = (Integer) entry.getValue();
        entry.setValue(new Integer(i.intValue() + 1));
        return null;
        }
    }

EntryProcessorsは個別に自動実行されますが、InvocableMap.invokeAll()を使用して複数のEntryProcessorを起動しても、1つのアトミック単位としては実行されません。個々のEntryProcessorが完了すると、他のEntryProcessorsが実行中であっても、キャッシュに対して行われたすべての更新がただちに表示されます。さらに、EntryProcessorで捕捉されなかった例外によりその他の処理の実行が妨げられることはありません。EntryProcessorの実行中に、あるエントリの1次ノードに障害が発生した場合は、かわりにバックアップ・ノードにより実行されます。ただし、EntryProcessorの完了後にノードに障害が発生した場合、そのEntryProcessorはバックアップでは起動されません。

一般的に、EntryProcessorsは短時間で実行する必要があります。EntryProcessorsを長時間実行しているアプリケーションでは、分散サービスのスレッド・プール・サイズを増やして、分散サービスが実行するその他の操作が、長時間実行されているEntryProcessorによってブロックされないようにする必要があります。分散サービスのスレッド・プールの詳細は、「DistributedCacheサービスのパラメータ」を参照してください。

Coherenceには、一般的な使用例に対する複数のEntryProcessor実装が備わっています。それらのEntryProcessorsと並列データ処理に関する詳細は、データ・グリッドの指定に関する項を参照してください。

トランザクション・フレームワークAPIの使用方法

トランザクション・フレームワークAPIによって、TCMPクライアントは操作を実行して、問合せ、アグリゲータ、およびトランザクションのコンテキスト内の入力プロセッサを使用できます。トランザクションでは、クライアントに障害が発生した場合でも、パーティションおよびキャッシュ全体にわたって、読取りの一貫性と原子性の保証が実現します。フレームワークは、独自の並行性方針と記憶域実装、および失敗したトランザクションに対する独自のリカバリ・マネージャを利用します。


注意:

TransactionMap APIは非推奨となり、トランザクション・フレームワークAPIがかわりに推奨されています。この2つのAPIは相互に排他的です。

既知の制限事項

トランザクション・フレームワークAPIの制限事項は次のとおりです。

この項は、次のトピックで構成されています。

トランザクション・フレームワークAPIは、Coherence JCAリソース・アダプタの基礎となるトランザクション・フレームワークでもあります。リソース・アダプタの使用方法の詳細は、「Coherenceリソース・アダプタの使用方法」を参照してください。

トランザクション・キャッシュの定義

トランザクション・キャッシュは、トランザクション保証を提供する専用の分散キャッシュです。トランザクション・フレームワークAPIを使用してトランザクションを実行する場合は常に、トランザクション・キャッシュが必要です。トランザクション・キャッシュは、非トランザクション・キャッシュと相互操作はできません。

トランザクション・キャッシュは、実行時にトランザクション記憶域とリカバリを提供する一連の内部トランザクション・キャッシュとともに自動的に使用されます。また、トランザクション・キャッシュにより、トランザクションのデフォルト動作(内部トランザクション・キャッシュのデフォルト動作を含む)を実行時にオーバーライドすることも可能です。

トランザクション・キャッシュは、<transactional-scheme>要素を使用して、キャッシュ構成ファイル内で定義されます。トランザクション・スキームには、分散キャッシュ・スキームで使用可能な同じ要素と属性が数多く含まれます。<transactional-scheme>要素とそのサブ要素すべての詳細は、「transactional-scheme」を参照してください。


注意:

ニア・キャッシュ・スキーム内でのトランザクション・スキームの使用は、現時点ではサポートされていません。

次の例は、キャッシュ構成ファイル内でのトランザクション・キャッシュ・スキームの定義を示しています。このキャッシュの名前はMyTxCacheで、example-transactionalという名前の<transactional-scheme>にマップされています。キャッシュ名にも、tx-*表記規則を使用できます。この規則により、複数のキャッシュ・インスタンスはトランザクション・キャッシュ・スキームへの単一マッピングを使用できます。


注意:

  • 次の例に示されているように、<service-name>要素はオプションです。トランザクション・キャッシュ・スキームに<service-name>要素が含まれていない場合には、デフォルトのサービス名としてTransactionalCacheが使用されます。この場合、アプリケーションはデフォルトのサービス名を使用してトランザクション・サービスに接続する必要があります。「トランザクション接続の作成」を参照してください。


例25-4 トランザクション・キャッシュ定義の例

<caching-scheme-mapping>
   <cache-mapping>
      <cache-name>MyTxCache</cache-name>
      <scheme-name>example-transactional</scheme-name>
   </cache-mapping>
   ...
</caching-scheme-mapping>

<caching-schemes>
<!-- Transactional caching scheme. -->
   <transactional-scheme>
      <scheme-name>example-transactional</scheme-name>
      <service-name>TransactionalCache</service-name>
      <autostart>true</autostart>
      <thread-count>10</thread-count>
      <request-timeout>30000</request-timeout>
   </transactional-scheme>
   ...
</caching-schemes>

<transactional-scheme>要素では、スキーム参照の使用もサポートされています。次の例では、example-transactionalという名前の<transactional-scheme>base-transactionalという名前の<transactional-scheme>を参照します。

<caching-scheme-mapping>
   <cache-mapping>
      <cache-name>tx-*</cache-name>
      <scheme-name>example-transactional</scheme-name>
   </cache-mapping>
   ...
</caching-scheme-mapping>

<caching-schemes>
   <transactional-scheme>
      <scheme-name>example-transactional</scheme-name>
      <scheme-ref>base-transactional</scheme-ref>
      <thread-count>10</thread-count>
   </transactional-scheme>

   <transactional-scheme>
      <scheme-name>base-transactional</scheme-name>
      <service-name>TransactionalCache</service-name>
      <request-timeout>30000</request-timeout>
      <autostart>true</autostart>
   </transactional-scheme>
   ...
</caching-schemes>

トランザクション内でのキャッシュ操作の実行

アプリケーションは、次の3つの方法のいずれかで、トランザクション内でキャッシュ操作を実行します。

  • NamedCache APIの使用: アプリケーションは、NamedCache APIを使用して、トランザクション内でキャッシュ操作を暗黙的に実行します。

  • Connection APIの使用: アプリケーションは、Connection APIを使用して、トランザクション内でキャッシュ操作を明示的に実行します。

  • Coherenceリソース・アダプタの使用: Java EEアプリケーションは、Coherenceリソース・アダプタを使用して、Coherenceデータ・クラスタに接続し、分散(グローバル)トランザクションの一部としてキャッシュ操作を実行します。

NamedCache APIの使用

NamedCache APIを使用して、トランザクションのコンテキスト内でキャッシュ操作を暗黙的に実行できます。ただし、この方法では、アプリケーションはデフォルトのトランザクション動作を変更できません。たとえば、トランザクションはNamedCache APIアプローチの使用時には自動コミット・モードになります。つまり、各操作は正常に完了するとただちにコミットされます。複数の操作のスコープを単一のトランザクションに設定することはできません。トランザクション動作をさらに制御する必要のあるアプリケーションは、Connection APIを使用する必要があります。トランザクションのデフォルト動作の詳細は、「トランザクション接続の使用方法」を参照してください。

NamedCache APIアプローチは、putAllなどの単一操作を実行する際に、原子性保証の確認に適した理想的な方法です。次の例では、NamedCacheインスタンスを作成し、CacheFactory.getCache()メソッドを使用してトランザクション・キャッシュを取得する単一クライアントを示しています。この例では、例25-4で定義されたトランザクション・キャッシュを使用しています。クライアントは、すべてのput操作が正常に実行された場合にのみコミットされるputAll操作を実行します。トランザクションは、任意のput操作が失敗すると、自動的にロールバックされます。

...
String key = "k";
String key2 = "k2";
String key3 = "k3";
String key4 = "k4";

CacheFactory.ensureCluster();
NamedCache cache = CacheFactory.getCache("MyTxCache");

Map map = new HashMap();
map.put(key, "value");
map.put(key2, "value2");
map.put(key3, "value3");
map.put(key4, "value4");

//operations performed on the cache are atomic
cache.putAll(map);

CacheFactory.shutdown();
...

Connection APIの使用

Connection APIは、トランザクション内でキャッシュ操作を実行するために使用され、トランザクション動作を明示的に制御する機能を提供します。たとえば、アプリケーションは自動コミット・モードを有効または無効にしたり、トランザクションの分離レベルを変更できます。

この項の例では、com.tangosol.coherence.transactionパッケージ内にあるConnectionインタフェース、DefaultConnectionFactoryクラスおよびOptimisticNamedCacheインタフェースの使用法を示しています。この例では、例25-4で定義されたトランザクション・キャッシュを使用しています。Connection APIの詳細は、次の例を参照してください。

例25-5では自動コミット・トランザクションを示しており、ここにある2つのinsert操作はそれぞれ、個別のトランザクションとして実行されます。

例25-5 自動コミット・トランザクションの実行

...
Connection con = new DefaultConnectionFactory().
   createConnection("TransactionalCache");

OptimisticNamedCache cache = con.getNamedCache("MytxCache");

cache.insert(key, value);
cache.insert(key2, value2);

con.close();
...

例25-6では非自動コミット・トランザクションを示しており、ここにある2つのinsert操作は単一のトランザクション内で実行されます。非自動コミット・トランザクションを使用するアプリケーションは、トランザクション境界を手動で定める必要があります。

例25-6 非自動コミット・トランザクションの実行

...
Connection con = new DefaultConnectionFactory().
   createConnection("TransactionalCache");

con.setAutoCommit(false);

try
   {
   OptimisticNamedCache cache = con.getNamedCache("MyTxCache");

   cache.insert(key, value);
   cache.insert(key2, value2);
   con.commit();

catch (Exception e)
   {
   con.rollback();
   throw e;
   }

finally
   {
   con.close();
   }
...

例25-7は、複数のキャッシュにわたるトランザクションの実行を示しています。各トランザクション・キャッシュは、キャッシュ構成ファイルで定義する必要があります。

例25-7 複数のキャッシュにわたるトランザクション

...
Connection con = new DefaultConnectionFactory().
   createConnection("TransactionalCache");

con.setAutoCommit(false);
OptimisticNamedCache cache = con.getNamedCache("MyTxCache");
OptimisticNamedCache cache1 = con.getNamedCache("MyTxCache1");

cache.insert(key, value);
cache1.insert(key2, value2);

con.commit();

con.close();
...

注意:

トランザクションは、同じサービス内にある複数のパーティションやキャッシュにまたがることがありますが、複数のサービスにまたがることはありません。

トランザクション接続の作成

com.tangosol.coherence.transaction.DefaultConnectionFactoryクラスは、com.tangosol.coherence.transaction.Connectionインスタンスの作成に使用します。例25-5に示した次のコードは、ファクトリの引数なしのコンストラクタを使用してConnectionインスタンスを作成する操作を示しています。

Connection con = new DefaultConnectionFactory().
   createConnection("TransactionalCache");

この例では、クラスパスで検出される(または-Dtangosol.coherence.cacheconfigシステム・プロパティを使用して指定される)最初の構成ファイルが、Connectionインスタンスによって使用されています。オプションで、キャッシュ構成ファイルの場所と名前を指定するファクトリ・クラスに、引数としてURIを渡すことができます。たとえば、次のコードは接続ファクトリを構成する操作を示しており、その接続ファクトリは、クラスパスで検出されたcache-config.xmlという名前のキャッシュ構成ファイル(configディレクトリに格納されている)を使用しています。

Connection con = new DefaultConnectionFactory("config/cache-config.xml").
   createConnection("TransactionalCache");

DefaultConnectionFactoryクラスは、接続を作成するメソッドを提供します。

  • createConnection(): この引数なしのメソッドは、デフォルトのトランザクション・サービスのメンバーである接続を作成します。これはTransactionalCacheと名付けられます。この引数なしのメソッドは、使用されている<transactional-scheme>要素に特定の<service-name>要素が含まれていない場合に使用します。トランザクション・キャッシュ・スキームの定義およびサービス名の指定の詳細は、「トランザクション・キャッシュの定義」を参照してください。

  • createConnection(ServiceName): このメソッドは、トランザクション・サービスのメンバーである接続を作成します。サービス名はStringで、この接続が属するトランザクション・サービスを示します。ServiceName<service-name>要素にマップされます。この要素は、キャッシュ構成ファイルの<transactional-scheme>内で定義されています。サービス名が使用されていない場合には、デフォルト名(TransactionalCache)がサービス名として使用されます。トランザクション・キャッシュ・スキームの定義およびサービス名の指定の詳細は、「トランザクション・キャッシュの定義」を参照してください。

  • createConnection(ServiceName, loader): このメソッドは、トランザクション・サービスのメンバーである接続を作成します。また、この構成を使用するクラス・ローダーを指定します。前述の例では、接続はサービス名の指定のみで作成され、その場合にはデフォルトのクラス・ローダーが使用されます。

トランザクション接続の使用方法

com.tangosol.coherence.transaction.Connectionインタフェースは、Coherenceサービスへの論理接続を表します。アクティブな接続は、常にトランザクションに関連付けられています。新規トランザクションは、接続が作成されたとき、およびトランザクションがコミットまたはロールバックされたときに、暗黙的に起動します。

接続から派生したトランザクションには、次に示す複数のデフォルトの動作があります。デフォルトの動作は、使いやすさとパフォーマンスのバランスをとります。

接続のデフォルト動作は、必要に応じてConnectionインスタンスのメソッドを使用して変更できます。

自動コミット・モードの使用方法

自動コミット・モードでは、各キャッシュ操作を別々のトランザクションに関連付けるかどうか、また複数のキャッシュ操作を単一のトランザクションとして実行するかどうかをアプリケーションで選択できます。各キャッシュ操作は、自動コミットが有効になっている場合に個別のトランザクションで実行されます。フレームワークでは、操作が完了して接続が新規トランザクションに関連付けられ、次の操作が実行された後で、トランザクションが自動的にコミットまたはロールバックされます。デフォルトでは、Connectionインスタンスが作成されている場合、自動コミットは有効です。

例25-5に示した次のコードは、それぞれが別々のトランザクションとして実行されるinsert操作を示しています。

OptimisticNamedCache cache = con.getNamedCache("MyTxCache");

cache.insert(key, value);
cache.insert(key2, value2);

自動コミット・モードを無効にすることで、複数の操作が単一トランザクションの一部として実行されます。自動コミット・モードが無効になっている場合には、アプリケーションはトランザクション境界を手動で定める必要があります。例25-6に示した次のコードは、単一トランザクション内で実行されるinsert操作を示しています。

con.setAutoCommit(false);

OptimisticNamedCache cache = con.getNamedCache("MyTxCache");

cache.insert(key, value);
cache.insert(key2, value2);

con.commit();

自動コミット・モードが有効になっている場合には、アプリケーションはcommit()メソッドまたはrollback()メソッドを使用できません。さらに、自動コミット・モードがアクティブ・トランザクションで有効になっている場合には、すべての作業が自動的にロールバックされます。

分離レベルの設定

分離レベルはデータの並行性と一貫性の制御に役立ちます。トランザクション・フレームワークは暗黙的な書込みロックを使用し、読取りロックを実装しません。ロックされたエントリに書き込もうとすると、UnableToAcquireLockExceptionが返され、リクエストはブロックしなくなります。トランザクションが即時モードに設定されている場合は、例外が即座にスローされます。非即時モードでは、例外がスローされるようになるのは文がフラッシュされたときで、それは通常、次の読取り時かトランザクションのコミット時です。「即時モードの使用方法」を参照してください。

Coherenceトランザクション・フレームワークAPIがサポートしている分離レベルは次のとおりです。

  • READ_COMMITTED: レベルが指定されていない場合、これがデフォルトの分離レベルです。この分離レベルは、コミットされたデータのみが参照可能になることを保証するもので、一貫性については保証しません。これは、分離レベルの中で最も弱く、通常、読取り一貫性を犠牲にして最善のパフォーマンスを実現します。

  • STMT_CONSISTENT_READ: この分離レベルでは、文スコープ設定読取り整合性が実現します。これは、単一の操作では、文が開始した時点で使用可能だった読取り一貫性バージョンのデータのみを読み取ることを保証するものです。このバージョンがキャッシュ内の最新データであるかどうかはわかりません。詳細は、次の「注意」を参照してください。

  • STMT_MONOTONIC_CONSISTENT_READ: この分離レベルでは、STMT_CONSISTENT_READと同じ保証が提供されますが、読取りも単調であることが保証されます。つまり、読取りで、この接続の使用中にすでに存在したすべてのバージョン以上であるバージョンが返されることが保証されます。単調な読取り保証であるため、この分離での読取りは、必要なバージョンが参照可能になるまでブロックします。

  • TX_CONSISTENT_READ: この分離レベルでは、トランザクションにスコープが設定された読取り一貫性が提供されます。この一貫性とは、指定されたトランザクションで実行された操作すべてが、トランザクションが開始した時点で使用可能だった読取り一貫性と同じ一貫性で読み取ったバージョンのデータを読み取ることを保証するものです。このバージョンがキャッシュ内の最新データであるかどうかはわかりません。詳細は、次の「注意」を参照してください。

  • TX_MONOTONIC_CONSISTENT_READ: この分離レベルでは、TX_CONSISTENT_READと同じ保証が提供されますが、読取りも単調であることが保証されます。つまり、読取りで、この接続の使用中にすでに存在したすべてのバージョン以上であるバージョンが返されることが保証されます。単調な読取り保証であるため、この分離でのトランザクションの初期読取りは、必要なバージョンが参照可能になるまでブロックします。


注意:

読取り一貫性分離レベル(文またはトランザクション)は、キャッシュ内の最新データより多少遅れることがあります。つまり、トランザクションが値を書き込んでコミットし、その値を次のトランザクションで読取り一貫性分離レベルの1つを使用して即座に読み取っても、更新された値をすぐに参照できない場合があります。最新値の読取りが重要な場合には、READ_COMMITTED分離レベルを使用する必要があります。

分離レベルはConnectionインスタンスに対して設定するものであり、アクティブ・トランザクションの開始前に設定する必要があります。例:

...
Connection con = new DefaultConnectionFactory(). createConnection("TransactionalCache");

con.setIsolationLevel(STMT_CONSISTENT_READ);
...

即時モードの使用方法

即時モードでは、クラスタ上でキャッシュ操作をいつ実行するかをアプリケーションで制御できます。即時モードが有効な場合には、キャッシュ操作はクラスタ上でただちに実行されます。即時モードが無効な場合には、キャッシュ操作は遅延され(可能な場合)、キューに入れられてバッチ処理として実行されます。通常、操作をキューに入れられるのは、値を返さない場合のみです。アプリケーションは、即時モードを無効にすることでパフォーマンスを向上できます。

デフォルトでは、即時モードは有効で、キャッシュ操作はクラスタ上でただちに実行されます。次の例は、即時モードの無効化を示します。

...
Connection con = new DefaultConnectionFactory(). createConnection("TransactionalCache");

con.setEager(false);
...

トランザクション・タイムアウトの設定

トランザクション・タイムアウトによって、トランザクションがロールバックされるまでアクティブにしておける時間をアプリケーションで制御できます。トランザクション・タイムアウトは、現在のトランザクション、および接続に関連付けられている新規トランザクションに関連付けられています。

タイムアウトの値は秒で指定されます。デフォルトのタイムアウト値は300秒です。次の例では、トランザクション・タイムアウト値の設定を示しています。

...
Connection con = new DefaultConnectionFactory(). createConnection("TransactionalCache");

con.setTransactionTimeout(420);
...

OptimisticNamedCacheインタフェースの使用方法

com.tangosol.coherence.transaction.OptimisticNamedCacheインタフェースはNamedCacheインタフェースを拡張し、update()delete()insert()の各操作を追加します。

トランザクション・キャッシュはすべて、このタイプから派生します。このキャッシュ・タイプでは、フレームワークの並行性とデータ・ロック実装がアプリケーションで使用されていることが確認されます。


注意:

OptimisticNamedCacheは、独自のロック方針を使用するため、ConcurrentMapインタフェースからの操作を拡張しません。

例25-5に示した次のコード・サンプルでは、MyTxCacheというトランザクション・キャッシュの取得を示し、キャッシュに対して操作を実行します。この例の場合、トランザクション・キャッシュMyTxCacheは、実行時にはキャッシュ構成ファイルに格納されている必要があります。トランザクション・キャッシュの定義の詳細は、「トランザクション・キャッシュの定義」を参照してください。

OptimisticNamedCache cache = con.getNamedCache("MyTxCache");

cache.insert(key, value);
cache.insert(key2, value2);

トランザクション実行時のPOFの構成

トランザクション・キャッシュは、トランザクション内のPortable Object Format(POF)シリアライズをサポートしています。POFは、<serializer>要素を使用してトランザクション・キャッシュ・スキーム内で有効化されます。次の例は、トランザクション・キャッシュ・スキーム内のPOFシリアライズの有効化を示しています。

<transactional-scheme>
   <scheme-name>example-transactional</scheme-name>
   <service-name>TransactionalCache</service-name>
   <autostart>true</autostart>
   <serializer>
      <class-name>com.tangosol.io.pof.ConfigurablePofContext</class-name>
   </serializer>
</transactional-scheme>

トランザクション・フレームワークAPIには、coherence.jarに格納されているtxn-pof-config.xml POF構成ファイルで定義されている独自のPOFタイプも含まれています。POFタイプは必須であり、実行時に検出される必要があります。

実行時にトランザクションPOFタイプをロードするには、アプリケーションのPOF構成ファイルを変更し、<include>要素を使用してtxn-pof-config.xml POF構成ファイルを追加します。例:

<pof-config>
  <user-type-list>
    <include>txn-pof-config.xml</include>
    ...
</pof-config>

<include>を使用してPOF構成ファイルを組み合せる方法の詳細は、「複数のPOF構成ファイルの組合せ」を参照してください。

トランザクション記憶域容量の構成

トランザクション・フレームワークAPIは、バッキング・マップを利用する内部分散キャッシュにトランザクション・データを格納します。このデータには、すべてのキーのバージョンと、トランザクション・キャッシュに対するキーの値が含まれます。フレームワークは、格納されたデータをロールバック・シナリオで、またリカバリ中にも使用します。

内部記憶域の要件によって、トランザクション・キャッシュでは、キャッシュに書き込まれた各エントリに一定のオーバーヘッドが関連付けられています。さらに、トランザクション・キャッシュは複数バージョンの並行性処理制御を使用します。つまり、書込み操作ごとに、それが更新であっても、キャッシュに新規の行が生成されます。したがって、トランザクション・フレームワークAPIでは、カスタム・エビクション・ポリシーを使用して、内部記憶域キャッシュの増加を管理できます。エビクション・ポリシーは、エントリのどのバージョンを保持し、どのバージョンがエビクションに適しているかを決定することで機能します。指定されたキー(最新)の最新バージョンは追い出されません。エビクション・ポリシーは、構成済の高水位標に達すると常に施行されます。しきい値に達すると、該当するバージョンの25%が削除されます。


注意:

  • エビクション・ポリシーは、高水位標を比較する際に、トランザクション記憶域全体を考慮するわけではありません。したがって、トランザクション記憶域は、記憶域のエビクション・ポリシーが認識されるまでに高水位標を少し超えることもあります。

  • 現在のキー・エントリが排出されることはないため、キャッシュが十分に広くても(個別キーの数が多くても)トランザクション・キャッシュの記憶域が最大ヒープ・サイズを超える可能性があります。


記憶域のエビクション・ポリシーは、測定された記憶域サイズが高水位標を超えると書込みごとに通知されるため、デフォルトの高水位標を、現在のデータ・セットのサイズより大きくなるように増加させる必要があります。増加させないと、現在のデータ・セットのサイズが高水位標を超えてパフォーマンスが低下すると、エビクション・ポリシーは書込みごとに通知されます。読取り一貫性が使用されない場合、履歴バージョンが読み取られることはないため、現在のデータ・セットの値は予測されるサイズを少し超えるように設定できます。読取り一貫性を使用する際には、高水位標を高く設定して、十分な数の履歴バージョンを提供できるようにします。トランザクション記憶域のサイズを概算するには、次に示す計算式を使用できます。

高水位標は、トランザクション・スキームの定義内の<high-units>要素を使用して構成されます。次の例は、高水位標を20MBに構成する処理を示しています。

<transactional-scheme>
   ...
   <high-units>20M</high-units>
   ...
</trnsactional-scheme>

次の計算式により、トランザクション・キャッシュの行に対するメモリー使用量の概算値を求めることができます。

挿入操作は次のとおりです。

  • プライマリ: キー(シリアライズ)+キー(ヒープ上のサイズ)+値(シリアライズ)+ 1095バイトの一定のオーバーヘッド

  • バックアップ: キー(シリアライズ)+値(シリアライズ)+ 530バイトの一定のオーバーヘッド

更新操作は次のとおりです。

  • プライマリ: 値(シリアライズ)+ 685バイトの一定のオーバーヘッド

  • バックアップ: 値(シリアライズ)+ 420バイトの一定のオーバーヘッド

Java拡張クライアントからのトランザクションの実行

トランザクション・フレームワークAPIでは、Java拡張クライアントがトランザクション内でキャッシュ操作を実行できます。この場合、トランザクションAPIは、クラスタ上に配置された入力プロセッサ内で使用します。実行時には、入力プロセッサをJavaクライアントのかわりに実行します。

この項の手順には、Coherence*Extendの設定方法や使用方法の詳細は記載されていません。それらのCoherence*Extendに対する新たな情報は、『Oracle Coherenceクライアント・ガイド』のCoherence*Extendの設定に関する項を参照してください。C++クライアントまたは.NETクライアントからのトランザクション実行の詳細は、『Oracle Coherenceクライアント・ガイドGuide』のC++クライアントに対するトランザクションの実行および.NETクライアントに対するトランザクションの実行に関する項を参照してください。

この項は、Java拡張クライアントからトランザクションへの実行に必要な次のトピックで構成されています。

トランザクション用の入力プロセッサの作成

トランザクションは、クラスタ上にある入力プロセッサ内でトランザクションAPIを使用して実行されます。入力プロセッサは、Java拡張クライアントのかわりに実行します。

例25-8では、トランザクション内で単純なupdate操作を実行する入力プロセッサを示しています。実行時には、入力プロセッサをクライアントとクラスタの両方に配置する必要があります。

例25-8 拡張クライアント・トランザクション用の入力プロセッサ

public class MyTxProcessor extends AbstractProcessor
   {
   public Object process(InvocableMap.Entry entry)
   {
      // obtain a connection and transaction cache
      ConnectionFactory connFactory = new DefaultConnectionFactory();
      Connection conn = connFactory.createConnection("TransactionalCache");
      OptimisticNamedCache cache = conn.getNamedCache("MyTxCache");
 
      conn.setAutoCommit(false);
 
      // get a value for an existing entry
      String sValue = (String) cache.get("existingEntry");
 
      // create predicate filter
      Filter predicate = new EqualsFilter(IdentityExtractor.INSTANCE, sValue);
 
      try
         {
            // update the previously obtained value
            cache.update("existingEntry", "newValue", predicate);
         }
      catch (PredicateFailedException e)
         {
            // value was updated after it was read
            conn.rollback();
            return false;
         }
      catch (UnableToAcquireLockException e)
         {
            // row is being updated by another tranaction
            conn.rollback();
            return false;
         }
      try
         {
            conn.commit();
         }
      catch (RollbackException e)
         {
            // transaction was rolled back
            return false;
         }
      return true;
   }
}

クラスタ側のトランザクション・キャッシュの構成

トランザクションでは、トランザクション・キャッシュをクラスタ側のキャッシュ構成ファイルで定義する必要があります。トランザクション・キャッシュの定義の詳細は、「トランザクション・キャッシュの定義」を参照してください。

次の例では、MyTxCacheというトランザクション・キャッシュを定義しています。これは、例25-8の入力プロセッサで使用されたキャッシュ名です。この例では、リモート・クライアントから入力プロセッサを実行するために必要なプロキシ・スキームと分散キャッシュ・スキームも含まれています。プロキシは、ポート9099localhostにおけるクライアントのTCP/IP接続を受け入れるように構成されています。

<cache-config>
   <caching-scheme-mapping>
      <cache-mapping>
         <cache-name>MyTxCache</cache-name>
         <scheme-name>example-transactional</scheme-name>
      </cache-mapping>
      <cache-mapping>
         <cache-name>dist-example</cache-name>
         <scheme-name>example-distributed</scheme-name>
      </cache-mapping>
   </caching-scheme-mapping>
 
   <caching-schemes>
      <transactional-scheme>
         <scheme-name>example-transactional</scheme-name>
         <task-timeout>0</task-timeout>
         <thread-count>7</thread-count>
         <autostart>true</autostart>
         <high-units>15M</high-units>
      </transactional-scheme>
      <distributed-scheme>
         <scheme-name>example-distributed</scheme-name>
         <service-name>DistributedCache</service-name>
         <backing-map-scheme>
            <local-scheme/>
         </backing-map-scheme>
        <autostart>true</autostart>
      </distributed-scheme>
      <proxy-scheme>
         <service-name>ExtendTcpProxyService</service-name>
         <thread-count>5</thread-count>
         <acceptor-config>
            <tcp-acceptor>
               <local-address>
                  <address>localhost</address>
                  <port>9099</port>
               </local-address>
            </tcp-acceptor>
         </acceptor-config>
        <autostart>true</autostart>
      </proxy-scheme>
   </caching-schemes>
</cache-config>

クライアント側のリモート・キャッシュの構成

クラスタのプロキシに接続してトランザクション入力プロセッサを実行するには、リモート・クライアントにリモート・キャッシュが必要です。リモート・キャッシュは、クライアント側のキャッシュ構成ファイルで定義します。

次の例では、リモート・キャッシュをポート9099localhostに配置されているプロキシに接続するように構成します。また、リモート・キャッシュの名前(dist-example)はトランザクション入力プロセッサの開始時に使用されるクラスタ側のキャッシュの名前と一致している必要があります。

<cache-config>
   <caching-scheme-mapping>
      <cache-mapping>
         <cache-name>dist-example</cache-name>
         <scheme-name>extend</scheme-name>
      </cache-mapping>
   </caching-scheme-mapping>
 
   <caching-schemes>
      <remote-cache-scheme>
         <scheme-name>extend</scheme-name>
         <service-name>ExtendTcpCacheService</service-name>
         <initiator-config>
            <tcp-initiator>
               <remote-addresses>
                  <socket-address>
                     <address>localhost</address>
                     <port>9099</port>
                  </socket-address>
               </remote-addresses>
               <connect-timeout>30s</connect-timeout>
            </tcp-initiator>
            <outgoing-message-handler>
               <request-timeout>30s</request-timeout>
            </outgoing-message-handler>
         </initiator-config>
      </remote-cache-scheme>
   </caching-schemes>
</cache-config>

Javaクライアントからのトランザクション入力プロセッサの使用

Java拡張クライアントが、通常どおり入力プロセッサを起動します。ただし、実行時にはクラスタ側の入力プロセッサが起動されます。クライアントは起動が委任されたことを認識しません。次の例は、例25-8に示された入力プロセッサをJavaクライアントが呼び出す方法を示しています。

NamedCache  cache    =  CacheFactory.getCache("dist-example");
Object      oReturn  = cache.invoke("AnyKey",  new MyTxProcessor());
 
System.out.println("Result of extend tx execution: " + oReturn);

トランザクション管理情報の表示

トランザクション・フレームワークは、既存のCoherence JMX管理フレームワークを活用します。Coherence JMX管理フレームワークの有効化および使用の詳細は、第34章「JMXを使用したCoherenceの管理方法」を参照してください。

この項では、トランザクション情報の表示に使用できる2つのMBean(CacheMBeanおよびTransactionManagerMBean)について説明します。

トランザクション・キャッシュのCacheMBean

CacheMBean管理対象リソースは、トランザクション・キャッシュを含むすべてのキャッシュに対して属性と操作を提供します。MBeanの属性の多くは、単に-1という値を返すような属性を起動するトランザクション・キャッシュには使用できません。クラスタ・ノードには、トランザクション・キャッシュのキャッシュ・マネージドBeanのインスタンスをゼロ個以上指定できます。オブジェクト名に使用される形式は次のとおりです。

type=Cache, service=service name, name=cache name, nodeId=cluster node's id

表25-2は、トランザクション・キャッシュをサポートするCacheMBean属性を示しています。

表25-2 トランザクション・キャッシュのサポートされている属性

属性 説明

AverageGetMillis

Double

get()の呼出しにかかった平均時間(ミリ秒)。

AveragePutMillis

Double

キャッシュ統計が最後にリセットされてからのput()の呼出しにかかった平均時間(ミリ秒)。

説明

String

キャッシュの説明。

HighUnits

Integer

キャッシュ・サイズの測定単位の制限。キャッシュが最大単位レベルに達すると、そのキャッシュは自動的に削除されます。これは通常、キャッシュの高水位標と呼ばれます。

Size

Integer

現在のデータ・セット内のエントリの数。

TotalGets

Long

キャッシュ統計が最後にリセットされてからのget()操作の合計数。

TotalGetsMillis

Long

キャッシュ統計が最後にリセットされてからのget()操作にかかった時間の合計(ミリ秒)。

TotalPuts

Long

キャッシュ統計が最後にリセットされてからのput()操作の合計数。

TotalPutsMillis

Long

キャッシュ統計が最後にリセットされてからのput()操作にかかった時間の合計(ミリ秒)。


トランザクション・キャッシュの場合、resetStatistics操作がサポートされ、トランザクション・マネージャの統計がすべてリセットされます。

TransactionManagerBean

TransactionManagerMBean管理対象リソースは、トランザクション・フレームワーク専用です。これには、すべてのトランザクション・サービス・インスタンスからのサービスレベルの統計を集計したグローバル・トランザクション・マネージャの統計が用意されています。各クラスタ・ノードには、サービスごとにトランザクション・マネージャの管理対象Beanのインスタンスがあります。オブジェクト名に使用される形式は次のとおりです。

type=TransactionManager, service=service name, nodeId=cluster node's id


注意:

特定のトランザクション・マネージャの属性については、複数のノードがトランザクションに参加していた可能性がある場合でも、トランザクションのコーディネータ・ノードでこの数は保持されます。たとえば、トランザクションには複数のノードに格納されているエントリに対する変更が追加されている場合がありますが、TotalCommitted属性はそのトランザクションのコミットを調整したノード上でのみMBeanで増分されます。

表25-3は、TransactionManager属性を説明しています。

表25-3 TransactionManagerMBean属性

属性 説明

TotalActive

Long

現在アクティブなトランザクションの合計数。アクティブなトランザクションは、少なくとも1つの変更されたエントリを含むトランザクションとして数えられ、まだコミットまたはロールバックされていません。複数のノードがトランザクションに参加していた可能性がある場合でも、トランザクションのコーディネータ・ノードでこの数は保持されます。

TotalCommitted

Long

最後に統計がリセットされてから、トランザクション・マネージャがコミットしたトランザクションの合計数。複数のノードがトランザクションに参加していた可能性がある場合でも、コミットされたトランザクションのコーディネータ・ノードでこの数は保持されます。

TotalRecovered

Long

最後に統計がリセットされてから、トランザクション・マネージャがリカバリしたトランザクションの合計数。複数のノードがトランザクションに参加していた可能性がある場合でも、リカバリされたトランザクションのコーディネータ・ノードでこの数は保持されます。

TotalRolledback

Long

最後に統計がリセットされてから、トランザクション・マネージャがロールバックしたトランザクションの合計数。複数のノードがトランザクションに参加していた可能性がある場合でも、ロールバックされたトランザクションのコーディネータ・ノードでこの数は保持されます。

TotalTransactionMillis

Long

アクティブなトランザクションでかかった累積時間(ミリ秒)。

TimeoutMillis

Long

トランザクション・タイムアウト値(ミリ秒)。この値は、値の設定後に取得されたトランザクション接続にのみ適用します。この属性は、現時点ではサポートされていません。


TransactionManagerMBeanには、すべてのトランザクション・マネージャの統計をリセットするresetStatisticsという単一操作が組み込まれています。

Coherenceリソース・アダプタの使用方法

Coherenceには、Coherenceキャッシュに接続するために使用するJ2EE Connector Architecture(J2CA)1.5準拠のリソース・アダプタが組み込まれています。このリソース・アダプタは、Coherenceトランザクション・フレームワークの接続APIを活用するため、デフォルトのトランザクション保証が用意されています。さらに、リソース・アダプタには、Coherenceがグローバル・トランザクションに参加できるXAが完全にサポートされています。グローバル・トランザクションは、1つ以上のリソース・マネージャが管理する作業の単位で、WebLogic ServerまたはOC4Jとともに組み込まれたトランザクション・マネージャなど、外部トランザクション・マネージャによって制御および調整されます。

リソース・アダプタは標準リソース・アダプタ・アーカイブ(RAR)としてパッケージ化され、coherence-transaction.rarと名付けられています。リソース・アダプタはCOHERENCE_HOME/libの中にあり、J2CA 1.5と互換性のあるすべてのJava EEコンテナにデプロイできます。リソース・アダプタには、専用のリソース・アダプタ・デプロイメント・ディスクリプタ(WebLogic用はweblogic-ra.xml、OC4J用はoc4j-ra.xml)が組み込まれ、変更しないでこれらのプラットフォームにデプロイできます。RARに組み込むことができる専用のリソース・アダプタ・ディスクリプタの定義の詳細は、アプリケーション・サーバーのベンダーのドキュメントを参照してください。


注意:

Coherenceには、下位互換性のためにcoherence-tx.rarリソース・アダプタが引き続き組み込まれます。ただし、アプリケーションではXAを完全にサポートするcoherence-transaction.rarリソース・アダプタを使用されることを強くお薦めします。CoherenceのCacheAdapterクラスを使い慣れている場合には、どちらのリソース・アダプタを引き続き使用してもかまいません。「トランザクション用のCoherenceキャッシュ・アダプタの使用方法」を参照してください。

この項は、次のトピックで構成されています。

トランザクション内でのキャッシュ操作の実行

Java EEアプリケーション・コンポーネント(サーブレット、JSPおよびEJB)では、Coherenceリソース・アダプタを使用して、トランザクション内でキャッシュ操作を実行します。リソース・アダプタは、ローカル・トランザクションとグローバル・トランザクションの両方をサポートします。ローカル・トランザクションは、Coherenceキャッシュにのみスコープが設定されていてグローバル・トランザクションに参加できないトランザクションの中でキャッシュ操作を実行する場合に使用します。グローバル・トランザクションは、トランザクションに参加している複数のリソースの結果に基づいて自動的にコミットまたはロールバックするキャッシュ操作を実行する場合に使用します。

すべてのJavaEEアプリケーション・コンポーネントのように、Java Naming and Directory Interface(JNDI)APIはリソース・アダプタの接続ファクトリの検索に使用されます。接続ファクトリはCoherenceキャッシュへの論理接続の取得に使用されます。

次の例では、Coherenceリソース・アダプタを使用してグローバル・トランザクション内でキャッシュ操作を実行する方法を示します。例25-9は、コンテナ管理のトランザクション(CMT)の使用例です。この場合、コンテナではすべてのメソッドが確実にグローバル・トランザクションの範囲内で実行しています。例25-10は、ユーザー制御トランザクションの例です。この場合、アプリケーション・コンポーネントではJavaトランザクションAPI(JTA)を使用してトランザクションの境界を手動で定めます。

トランザクションでは、トランザクション・キャッシュ・スキームをキャッシュ構成ファイル内で定義する必要があります。これらの例では、例25-4で定義されたトランザクション・キャッシュを使用しています。

例25-9 CMT使用時のトランザクションの実行

Context initCtx = new InitialContext();ConnectionFactory cf = (ConnectionFactory)
 initCtx.lookup("java:comp/env/eis/CoherenceTxCF");

Connection con = cf.createConnection("TransactionalCache");

try
   {
   OptimisticNamedCache cache = con.getNamedCache("MyTxCache");

   cache.delete("key1", null);
   cache.insert("key1", "value1");
   }
finally
   {
   con.close();
   }

例25-10 ユーザー制御トランザクションの実行

Context initCtx = new InitialContext();
ConnectionFactory cf = (ConnectionFactory)
 initCtx.lookup("java:comp/env/eis/CoherenceTxCF");

UserTransaction ut = (UserTransaction) new
 InitialContext().lookup("java:comp/UserTransaction");
ut.begin();

Connection con = cf.createConnection("TransactionalCache");

try
   {
   OptimisticNamedCache cache = con.getNamedCache("MyTxCache");

   cache.delete("key1", null);
   cache.insert("key1", "value1");
   ut.commit();
   }

catch (Exception e)
   {
   ut.rollback();
   throw e;
   }

finally
   {
   con.close();
   }

Coherence接続の作成

アプリケーションでは、com.tangosol.coherence.ConnectionFactoryインタフェースを使用して、Coherenceクラスタへの接続を作成します。このインタフェースのインスタンスは、JNDIルックアップを使用して取得します。例25-10に示した次のコード・サンプルでは、java:comp/env/eis/CoherenceTxCFネームスペースにバインドされた接続ファクトリのJNDIルックアップを実行します。

Context initCtx = new InitialContext();ConnectionFactory cf = (ConnectionFactory)
   initCtx.lookup("java:comp/env/eis/CoherenceTxCF");

ConnectionFactoryは、com.tangosol.coherence.transaction.Connectionインスタンスの作成に使用されます。Connectionインスタンスは、Coherenceサービスへの論理接続を表します。

Connection con = cf.createConnection("TransactionalCache");

creatConnection(ServiceName)メソッドは、トランザクション・サービスのメンバーである接続を作成します。サービス名は、この接続が属するトランザクション・サービスを示すStringで、これはキャッシュ構成ファイル内の<transactional-scheme>で定義されるサービス名にマップする必要があります。トランザクション・キャッシュ・スキームの定義およびサービス名の指定の詳細は、「トランザクション・キャッシュの定義」を参照してください。

Connectionインスタンスには常に、接続内にスコープ設定された関連トランザクションがあります。新規トランザクションは、トランザクションが完了したときに起動します。次のデフォルトの動作は、接続に関連付けられています。Connectionインタフェース、およびデフォルト設定の変更の詳細は、「トランザクション接続の使用方法」を参照してください。

  • 接続はデフォルトで自動コミット・モードです。つまり、各文は個別トランザクション内で実行され、文が完了するときトランザクションはコミットされ、接続は新規トランザクションに関連付けられます。


    注意:

    接続がグローバル・トランザクションのコンテキストで使用されると、自動コミット・モードは無効になり、有効化できません。これは、すべてのキャッシュ操作が単一のトランザクションで実行され、1つの単位としてコミットまたはロールバックするということです。また、Connectionインタフェースのcommitメソッドおよびrollbackメソッドは、接続がグローバル・トランザクションに参加している場合には使用できません。

  • 接続の分離レベルは、READ_COMMITTEDに設定されています。つまり、トランザクションは他のトランザクションからコミットされたデータのみを表示できます。

  • 即時モードはデフォルトで有効にされています。これは、操作ごとにクラスタへただちにフラッシュされ、バッチ処理でフラッシュされるようにキューに配置されないということです。

  • デフォルトのトランザクション・タイムアウトは300秒です。


    注意:

    接続がグローバル・トランザクションのコンテキストで使用されると、接続に関連付けられているトランザクション・タイムアウトは、コンテナのJTA構成で設定されたトランザクション・タイムアウト値でオーバーライドされます。接続がグローバル・トランザクションに参加しているときに、アプリケーションが接続上でトランザクション・タイムアウト値を設定しようとすると、その試行は無視され、警告メッセージが表示されて、トランザクション・タイムアウトが設定できないことが示されます。接続上に設定された元のタイムアウト値は、グローバル・トランザクションが完了した後に回復します。

名前付きキャッシュの取得

com.tangosol.coherence.transaction.OptimisticNamedCacheインタフェースは、NamedCacheインタフェースを拡張したものです。これは、慣例により名付けられたキャッシュ操作をすべてサポートし、更新オブジェクト、削除オブジェクトおよび挿入オブジェクトに対する独自の操作をキャッシュに追加します。トランザクションの実行時には、すべてのキャッシュ・インスタンスがこのタイプから派生する必要があります。例25-10に示した次のコード・サンプルは、MyTxCacheという名前付きキャッシュを取得し、そのキャッシュに対して操作を実行することを示しています。キャッシュは、キャッシュ構成ファイルで定義する必要があります。

try
   {
   OptimisticNamedCache cache = con.getNamedCache("MyTxCache");

   cache.delete("key1", null);
   cache.insert("key1", "value1");

注意:

OptimisticNamedCacheは、独自のロック方針を使用するため、ConcurrentMapインタフェースからの操作を拡張しません。

トランザクション境界の設定

ユーザー制御トランザクションを実行するアプリケーション・コンポーネントは、JNDIルックアップを使用してJTA UserTransactionインタフェースのインスタンスを取得します。このインタフェースには、トランザクションの境界を定めるメソッドが用意されています。例25-10に示した次のコード・サンプルでは、UserTransactionインスタンスを取得してトランザクションの境界を定める処理を示しています。

UserTransaction ut = (UserTransaction) new
 InitialContext().lookup("java:comp/UserTransaction");

ut.begin();
Connection con = cf.createConnection("TransactionalCache");

try
   {
   OptimisticNamedCache cache = con.getNamedCache("MyTxCache");

   cache.delete("key1", null);
   cache.insert("key1", "value1");
   ut.commit();

前述のコードは、接続と名前付きキャッシュがトランザクション境界内に存在する一般的なシナリオを示しています。ただし、リソース・アダプタは、トランザクション境界にまたがって接続を使用し、グローバル・トランザクションの起動前に接続を取得するというシナリオもサポートしています。例:

Connection con = cf.createConnection("TransactionalCache");

try
   {
   OptimisticNamedCache cache = con.getNamedCache("MyTxCache");

   cache.delete("key1", null);

   UserTransaction ut = (UserTransaction) new
    InitialContext().lookup("java:comp/UserTransaction");

   ut.begin();
   cache.insert("key1", "value1");
   ut.commit();

アプリケーションのパッケージ化

この項では、Coherenceリソース・アダプタを使用するJavaEEアプリケーションをパッケージ化して、JavaEEアプリケーションがアプリケーション・サーバーにデプロイできるようにする手順を説明します。この項は、次のトピックで構成されています。

接続ファクトリのリソース参照の構成

アプリケーション・コンポーネントには、リソース・アダプタの接続ファクトリのリソース参照が用意されている必要があります。EJBの場合、リソース参照はejb-jar.xmlデプロイメント・ディスクリプタで定義します。サーブレットとJSPの場合、リソース参照はweb.xmlデプロイメント・ディスクリプタで定義します。次のサンプルは、リソース・アダプタの接続ファクトリのリソース参照の定義を示したもので、例25-10のコードに適用されます。

<resource-ref>
   <res-ref-name>eis/CoherenceTxCF</res-ref-name>
   <res-type>
      com.tangosol.coherence.transaction.ConnectionFactory
   </res-type>
   <res-auth>Container</res-auth>
</resource-ref>

多くのアプリケーション・サーバーでは、Java EEアプリケーション・コンポーネントの標準的なデプロイメント・ディスクリプタ以外に、専用のデプロイメント・ディスクリプタも必要です。たとえば、WebLogic Serverリソース参照は、weblogic.xmlファイルとweblogic-ejb-jar.xmlファイルでそれぞれ定義されています。

<reference-descriptor>
   <resource-description>
      <res-ref-name>eis/CoherenceTxCF</res-ref-name>
      <jndi-name>tangosol.coherenceTx</jndi-name>
   </resource-description>
</reference-descriptor>

アプリケーション・コンポーネントの専用デプロイメント・ディスクリプタの使用法、および依存性インジェクションまたは注釈の使用を通じてリソース参照を定義するための代替方法の詳細は、アプリケーション・サーバーのベンダーのドキュメントを参照してください。

リソース・アダプタのモジュール参照の構成

JavaEEアプリケーションには、Coherenceリソース・アダプタのモジュール参照が用意されている必要があります。モジュール参照は、EARのapplication.xmlファイルで定義します。モジュール参照は、EARファイル内のCoherence RARファイル(coherence-transaction.rar)の場所をポイントします。たとえば、次の定義はEARファイルのルートに配置されたCoherenceリソース・アダプタのRARファイルをポイントします。

<application>
...
<module>
   <connector>coherence-transaction.rar</connector>
</module>
...
</application>

多くのアプリケーション・サーバーでは、Java EEアプリケーションの標準的なデプロイメント・ディスクリプタ以外に、専用のデプロイメント・ディスクリプタも必要です。たとえば、Coherenceリソース・アダプタは、WebLogic Serverのweblogic-application.xmlファイルで次のように定義されています。

<weblogic-application>
   <classloader-structure>
      ...
      <module-ref>
         <module-uri>coherence-transaction.rar</module-uri>
      </module-ref>
      ...
   </classloader-structure>
</weblogic-application>

アプリケーションの専用デプロイメント・ディスクリプタの使用方法の詳細は、アプリケーション・サーバーのベンダーのドキュメントを参照してください。

必要なライブラリの組込み

Coherenceリソース・アダプタを使用するJavaEEアプリケーションには、EARファイル内にcoherence-transaction.rarファイルとcoherence.jarファイルが含まれている必要があります。次の例では、ライブラリをEARファイルのルートに配置しています。

/
/coherence-transaction.rar
/coherence.jar

WebLogicサーバーにデプロイする際には、coherence.jarファイルはEARファイルの/APP-INF/libディレクトリに配置される必要があります。例:

/
/coherence-transaction.rar
/APP-INF/lib/coherence.jar

このデプロイメントのシナリオでは、1つのCoherenceクラスタ・ノードをEAR内のすべてのアプリケーション・コンポーネントが共有します。Coherenceデプロイメントの別のオプションは、第31章「Coherenceのデプロイ」を参照してください。

トランザクション用のCoherenceキャッシュ・アダプタの使用方法

Coherence CacheAdapterクラスは、トランザクションの作成に代替クライアントを使用する方法を提供するもので、coherence-tx.rarリソース・アダプタの使用時に必要となります。新規のcoherence-transaction.rarリソース・アダプタもCacheAdapterクラス(変更したものもいくつか含む)をサポートし、このクラスを使い慣れている人は、新規のリソース・アダプタの利点をいくつか活用できます。ただし、アプリケーションでは、Coherenceリソース・アダプタをネイティブに使用することをお薦めします。そうすると、より強力なトランザクションのサポートが実現します。どちらのリソース・アダプタの例も、この項で説明しています。

例25-11では、CacheAdapterクラスを新規のcoherence-transaction.rarリソース・アダプタで使用するときの、トランザクション内のキャッシュ操作の実行を示しています。この例の場合、トランザクション・キャッシュMyTxCacheは、キャッシュ構成ファイルで構成する必要があります。キャッシュは、サービス名TransactionalCacheでトランザクション・キャッシュ・スキームにマップする必要があります。トランザクション・キャッシュ・スキームの定義の詳細は、「トランザクション・キャッシュの定義」を参照してください。

例25-11 coherence-transaction.rar使用時のCacheAdapterクラスの使用方法

Context initCtx = new InitialContext();

CacheAdapter adapter = new CacheAdapter(initCtx,
   "java:comp/env/eis/CoherenceTxCCICF", 0, 0, 0);

adapter.connect("TransactionalCache", "scott", "tiger");

try
   {
   UserTransaction ut = (UserTransaction) new 
      InitialContext().lookup("java:comp/UserTransaction");

   ut.begin();
   OptimisticNamedCache cache =     (OptimisticNamedCache) adapter.getNamedCache("MyTxCache",
      getClass().getClassLoader());
   cache.delete("key", null);
   cache.insert("key", "value");
   ut.commit();
 
   }
finally
   {
   adapter.close();
   }

例25-12では、CacheAdapterクラスをcoherence-tx.rarリソース・アダプタで使用するときの、トランザクション内のキャッシュ操作の実行を示しています。

例25-12 coherence-tx.rar使用時のCacheAdapterクラスの使用方法

String          key = "key";
Context         ctx = new InitialContext();
UserTransaction tx  = null;
try
    {
    // the transaction manager from container
    tx = (UserTransaction) ctx.lookup("java:comp/UserTransaction");
    tx.begin();

    // the try-catch-finally block below is the block of code
    // that could be on an EJB and therefore automatically within
    // a transactional context
    CacheAdapter adapter = null;
    try
        {
        adapter = new CacheAdapter(ctx, "tangosol.coherenceTx",
                CacheAdapter.CONCUR_OPTIMISTIC,
                CacheAdapter.TRANSACTION_GET_COMMITTED, 0);

        NamedCache cache = adapter.getNamedCache("dist-test",
                getClass().getClassLoader());

        int n = ((Integer)cache.get(key)).intValue();
        cache.put(key, new Integer(++n));
        }
    catch (Throwable t)
        {
        String sMsg = "Failed to connect: " + t;
        System.err.println(sMsg);
        t.printStackTrace(System.err);
        }
    finally
        {
        try
            {
            adapter.close();
            }
        catch (Throwable ex)
            {
            System.err.println("SHOULD NOT HAPPEN: " + ex);
            }
        }
    }
finally
    {
    try
        {
        tx.commit();
        }
    catch (Throwable t)
        {
        String sMsg = "Failed to commit: " + t;
        System.err.println(sMsg);
        }
    }