11.3. トランザクションの最適化

11.3.1. トランザクション最適化の概要

JBoss EAP のトランザクションマネージャー (TM) には、アプリケーションで利用できる複数の最適化機能が含まれています。

最適化機能は、特定のケースで 2 フェーズコミットプロトコルを拡張するために使用します。一般的に、TM によって、2 フェーズコミットを介して渡されるグローバルトランザクションが開始されます。ただし、これらのトランザクションを最適化する場合、特定のケースでは TM によって完全な 2 フェーズコミットを行う必要がないため、処理は速くなります。

TM により使用される別の最適化機能は、以下で詳細に説明されています。

11.3.2. 1 フェーズコミット (1PC) の LRCO 最適化

1 フェーズコミット (1PC)

トランザクションでは、2 フェーズコミットプロトコル (2PC) がより一般的に使用されますが、両フェーズに対応する必要がなかったり、対応できない場合もあります。そのような場合、1 フェーズコミット (1PC) プロトコルを使用できます。1 フェーズコミットプロトコルは、XA または非 XA リソースの 1 つがグローバルトランザクションの一部である場合に使用されます。

一般的に、準備フェースでは、第 2 フェーズが処理されるまでリソースがロックされます。1 フェーズコミットは、準備フェースが省略され、コミットのみがリソースに対して処理されることを意味します。指定されない場合は、グローバルトランザクションに参加者が 1 つだけ含まれるときに 1 フェーズコミット最適化機能が自動的に使用されます。

最終リソースコミット最適化 (LRCO: Last Resource Commit Optimization)

非 XA データソースが XA トランザクションに参加する場合は、最終リソースコミット最適化 (LRCO) と呼ばれる最適化機能が使用されます。このプロトコルにより、ほとんどのトランザクションは正常に完了しますが、一部のエラーによってトランザクションの結果の一貫性が失われることがあります。そのため、この方法は最終手段として使用してください。

非 XA リソースは準備フェーズの終了時に処理され、コミットが試行されます。コミットに成功すると、トランザクションログが書き込まれ、残りのリソースがコミットフェーズに移動します。最終リソースがコミットに失敗すると、トランザクションはロールバックされます。

ローカルの TX データソースが 1 つのみトランザクションで使用されると、LRCO が自動的に適用されます。

これまでは、LRCO メソッドを使用して非 XA リソースを XA トランザクションに追加していました。ただし、この場合は LRCO が失敗する可能性があります。LRCO メソッドを用いて非 XA リソースを XA トランザクションに追加する手順は次のとおりです。

  1. XA トランザクションを準備します。
  2. LRCO をコミットします。
  3. トランザクションログを書き込みます。
  4. XA トランザクションをコミットします。

手順 2 と手順 3 の間でクラッシュした場合、データが不整合になり、XA トランザクションをコミットできなくなることがあります。データの不整合が発生する理由は、LRCO 非 XA リソースがコミットされても、XA リソースの準備に関する情報が記録されなかったことです。リカバリーマネージャーはサーバーの起動後にリソースをロールバックします。CMR (Commit Markable Resource) ではこの制限がなくなり、非 XA リソースが確実に XA トランザクションに登録できるようになります。

注記

CMR は、特別な LRCO 最適化機能であり、データソースのみに使用する必要があります。非 XA リソースには適していません。

11.3.2.1. Commit Markable Resource (CMR)

概要

Commit Markable Resource (CMR) インターフェイスを使用してリソースマネージャーへのアクセスを設定すると、非 XA データソースを XA (2PC) トランザクションに安定的に登録できます。これは、非 XA リソースを完全にリカバリー可能にする LRCO アルゴリズムの実装です。

CMR を設定するには、以下のことを行う必要があります。

  1. データベースでテーブルを作成します。
  2. データソースを接続可能にします。
  3. transactions サブシステムへの参照を追加します。
データベースでのテーブルの作成

トランザクションには CMR リソースを 1 つだけ含めることができます。以下の例と似た SQL を使用してテーブルを作成できます。

SELECT xid,actionuid FROM _tableName_ WHERE transactionManagerID IN (String[])
DELETE FROM _tableName_ WHERE xid IN (byte[[]])
INSERT INTO _tableName_ (xid, transactionManagerID, actionuid) VALUES (byte[],String,byte[])

以下は、さまざまなデータベース管理システムのテーブルを作成するための SQL 構文の例になります。

例: Sybase のテーブル作成構文

CREATE TABLE xids (xid varbinary(144), transactionManagerID varchar(64), actionuid varbinary(28))

例: Oracle のテーブル作成構文

CREATE TABLE xids (xid RAW(144), transactionManagerID varchar(64), actionuid RAW(28))
CREATE UNIQUE INDEX index_xid ON xids (xid)

例: IBM のテーブル作成構文

CREATE TABLE xids (xid VARCHAR(255) for bit data not null, transactionManagerID
varchar(64), actionuid VARCHAR(255) for bit data not null)
CREATE UNIQUE INDEX index_xid ON xids (xid)

例: SQL Server のテーブル作成構文

CREATE TABLE xids (xid varbinary(144), transactionManagerID varchar(64), actionuid varbinary(28))
CREATE UNIQUE INDEX index_xid ON xids (xid)

例: PostgreSQL のテーブル作成構文

CREATE TABLE xids (xid bytea, transactionManagerID varchar(64), actionuid bytea)
CREATE UNIQUE INDEX index_xid ON xids (xid)

例: MariaDB のテーブル作成構文

CREATE TABLE xids (xid BINARY(144), transactionManagerID varchar(64), actionuid BINARY(28))
CREATE UNIQUE INDEX index_xid ON xids (xid)

例: MySQL のテーブル作成構文

CREATE TABLE xids (xid VARCHAR(255), transactionManagerID varchar(64), actionuid VARCHAR(255))
CREATE UNIQUE INDEX index_xid ON xids (xid)

データソースを接続可能にする

デフォルトでは、CMR 機能はデータソースに対して無効になっています。有効にするには、データソースの設定を作成または変更し、connectable 属性を true に設定する必要があります。以下に、サーバーの XML 設定ファイルのデータソースセクションの例を示します。

<datasource enabled="true" jndi-name="java:jboss/datasources/ConnectableDS" pool-name="ConnectableDS" jta="true" use-java-context="true" connectable="true"/>
注記

この機能は XA データソースには適用されません。

また、以下のように管理 CLI を使用してリソースマネージャーを CMR として有効にすることもできます。

/subsystem=datasources/data-source=ConnectableDS:add(enabled="true", jndi-name="java:jboss/datasources/ConnectableDS", jta="true", use-java-context="true", connectable="true", connection-url="validConnectionURL", exception-sorter-class-name="org.jboss.jca.adapters.jdbc.extensions.mssql.MSSQLExceptionSorter", driver-name="mssql")

このコマンドは、サーバー設定ファイルの datasources セクションで以下の XML を生成します。

<datasource jta="true" jndi-name="java:jboss/datasources/ConnectableDS" pool-name="ConnectableDS" enabled="true" use-java-context="true" connectable="true">
  <connection-url>validConnectionURL</connection-url>
  <driver>mssql</driver>
  <validation>
    <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.mssql.MSSQLExceptionSorter"/>
  </validation>
</datasource>
注記

データソースには、有効なドライバーが定義されている必要があります。上記の例では、mssqldriver-name として使用されますが、mssql は存在しません。詳細は、JBoss EAP設定ガイドMySQL データソースの例を参照してください。

注記

データソース設定で exception-sorter-class-name パラメーターを使用します。詳細については、JBoss EAP設定ガイドデータソース設定の例を参照してください。

新しい CMR 機能を使用するために既存のリソースを更新

CMR 機能を使用するために既存のデータソースのみを更新する必要がある場合は、connectable 属性を変更します。

/subsystem=datasources/data-source=ConnectableDS:write-attribute(name=connectable,value=true)
transactions サブシステムに参照を追加

transactions サブシステムは、以下のような transactions サブシステム設定セクションへのエントリーを用いて CMR 対応のデータソースを特定します。

<subsystem xmlns="urn:jboss:domain:transactions:5.0">
    ...
    <commit-markable-resources>
        <commit-markable-resource jndi-name="java:jboss/datasources/ConnectableDS">
            <xid-location name="xids" batch-size="100" immediate-cleanup="false"/>
        </commit-markable-resource>
        ...
    </commit-markable-resources>
</subsystem>

以下のように管理 CLI を使用すると同じ結果を実現できます。

/subsystem=transactions/commit-markable-resource=java\:jboss\/datasources\/ConnectableDS/:add(batch-size=100,immediate-cleanup=false,name=xids)
注記

transactions サブシステムで CMR 参照を追加したら、サーバーを再起動する必要があります。

11.3.3. 推定中止 (presumed-abort) の最適化

トランザクションをロールバックする場合、この情報をローカルで記録し、エンリストされたすべての参加者に通知します。この通知は形式的なもので、トランザクションの結果には影響しません。すべての参加者が通知されると、このトランザクションに関する情報を削除できます。

トランザクションのステータスに対する後続の要求が行われる場合、利用可能な情報はありません。このような場合、要求側はトランザクションが中断され、ロールバックされたと見なします。推定中止 (presumed-abort) の最適化は、トランザクションがコミットの実行を決定するまで参加者に関する情報を永続化する必要がないことを意味します。 これは、トランザクションがコミットの実行を決定する前に発生した障害はトランザクションの中止であると推定されるためです。

11.3.4. 読み取り専用の最適化

参加者は、準備するよう要求されると、トランザクション中に変更したデータがないことをコーディネーターに伝えることができます。参加者が最終的にどうなってもトランザクションに影響を与えることはないため、このような参加者にトランザクションの結果について通知する必要はありません。この読み取り専用の参加者はコミットプロトコルの第 2 フェーズから省略可能です。