トランザクション

トランザクションとは

SkyOnDemandのトランザクション管理はJ2EEの標準的な枠組みである「JTA(Java Transaction API)」に準拠しています。
SkyOnDemandでは「スクリプト単位」と「指定した処理単位」でトランザクションを設定することができます。

スクリプトのトランザクション

「スクリプト単位」でトランザクションを設定する場合、6種類のトランザクション属性を選択することができます。
トランザクション属性は次の2つの観点で設定します。
  1. 呼び出し元のトランザクションの制限
    対象のスクリプトが以下のいずれかを設定します。
  2. 呼び出し元トランザクションの引き継ぎ
    対象のスクリプトが、呼び出し元のトランザクションを引き継いで、同一のトランザクションとして動作するかどうかを設定します。
トランザクション属性 呼び出し元トランザクションの制限 呼び出し元トランザクションの引き継ぎ 説明
NEVER 以下のトランザクション属性のスクリプトからは呼び出すことができません。
  • REQUIRED
  • REQUIRES_NEW
  • MANDATORY
呼び出し元トランザクションの引き継ぎは行いません。 トランザクションはサポートしません。
また、呼び出し元はトランザクションをサポートしていない必要があります。
NOT_SUPPORTED 制限はありません。
すべてのトランザクション属性のスクリプトから呼び出すことができます。
呼び出し元トランザクションの引き継ぎは行いません。 トランザクションはサポートしません。
また、呼び出し元のトランザクション属性に関わらず、そのトランザクションには参加しません。
SUPPORTS 制限はありません。
すべてのトランザクション属性のスクリプトから呼び出すことができます。
  • 呼び出し元がトランザクションをサポートしている場合は、そのトランザクションを引き継ぎ、同一のトランザクションとして動作します。
  • 呼び出し元がトランザクションをサポートしていない場合は、トランザクション処理を行いません。
デフォルトの動作は、トランザクションをサポートしません。
また、呼び出し元のトランザクション属性によって、サポートする/しないが変わります。
スクリプトのトランザクション属性のデフォルト値です。
REQUIRED 制限はありません。
すべてのトランザクション属性のスクリプトから呼び出すことができます。
  • 呼び出し元がトランザクションをサポートしている場合は、そのトランザクションを引き継ぎ、同一のトランザクションとして動作します。
  • 呼び出し元がトランザクションをサポートしていない場合は、新規にトランザクションを開始します。
トランザクションをサポートします。
呼び出し元のトランザクション属性によって、動作が変わります。
REQUIRES_NEW 制限はありません。
すべてのトランザクション属性のスクリプトから呼び出すことができます。
呼び出し元がトランザクションをサポートしている/していないに関わらず、新規にトランザクションを開始します。 トランザクションをサポートします。
常に新規にトランザクションを開始します。
MANDATORY 以下のトランザクション属性のスクリプトからは呼び出すことができません。
  • NEVER
  • NOT_SUPPORTED
  • SUPPORTS(呼び出し元がトランザクションサポートしていない場合)
呼び出し元のトランザクションを引き継ぎ、同一のトランザクションとして動作します。 トランザクションをサポートします。
また、呼び出し元は、必ずトランザクションをサポートしていなくてはなりません。

親スクリプトと子スクリプトのトランザクション属性の関係一覧表


トランザクション属性 設定の可否
子スクリプト 親スクリプト
NEVER NEVER
NOT_SUPPORTED
SUPPORTS
REQUIRED
×
REQUIRES_NEW
×
MANDATORY
×
NOT_SUPPORTED NEVER
NOT_SUPPORTED
SUPPORTS
REQUIRED
REQUIRES_NEW
MANDATORY
SUPPORTS NEVER
NOT_SUPPORTED
SUPPORTS
REQUIRED
REQUIRES_NEW
MANDATORY
REQUIRED NEVER
NOT_SUPPORTED
SUPPORTS
REQUIRED
REQUIRES_NEW
MANDATORY
REQUIRES_NEW NEVER
NOT_SUPPORTED
SUPPORTS
REQUIRED
REQUIRES_NEW
MANDATORY
MANDATORY NEVER
×
NOT_SUPPORTED
×
SUPPORTS
SUPPORTSが設定された
呼び出し元スクリプトが
トランザクションをサポート
している場合
REQUIRED
REQUIRES_NEW
MANDATORY

トランザクションコンポーネント

SkyOnDemandでは、「指定した処理」単位でもトランザクションを設定することができます。
指定した処理単位でトランザクションを設定する場合には、トランザクションコンポーネントを使用します。

トランザクションコンポーネントは常に新規のトランザクションを開始します。トランザクション属性のREQUIRES_NEWと同様の動作となります。

アダプタのトランザクション

トランザクションをサポートしているアダプタは通常、コンポーネントアイコン単位でトランザクション処理を行います。
スクリプトのトランザクション属性やトランザクションコンポーネント内に配置された場合などは、そのトランザクションに参加します。
ファイル系アダプタは動作が異なります。
詳細については、「ファイル系アダプタのトランザクション」を参照してください。

トランザクションのサポートの有無については、各アダプタのヘルプ内「トランザクション」項を参照してください。

XAリソースと非XAリソース

一部のアダプタのグローバルリソースにはXAリソースと非XAリソースがあります。
XAリソースとは、2フェーズコミットを有するグローバルトランザクションに対応したリソースのことで、非XAリソースとは2フェーズコミット機能を有さないリソースのことです。
グローバルトランザクション(分散トランザクションともいいます。)とは、複数のリソースにまたがったトランザクション処理のことです。

XAリソースと非XAリソースのトランザクション処理の違い

XAリソースを使用したときと、非XAリソースを使用したときのトランザクション処理の違いは以下の通りです。 XAリソースを使用した場合には、トランザクション完了前(コミットまたはロールバック前)に「プリペア」という処理が実行されます。このような処理を「2フェーズコミット」と呼びます。 複数のリソースにまたがるトランザクション処理では、このプリペア処理が重要な役割を果たします。

トランザクションの実例

以下で実際の動作を見ながら、XAリソースと非XAリソースの動作の違いを説明します。


上記スクリプトは、同一のトランザクションで処理を行います。
また、このスクリプトは「書き込み2」の処理が非常に長く、「書き込み1」の処理ではコミット時にトランザクションタイムアウトが発生するとします。 非XAリソースの場合

つまり非XAリソースの場合、トランザクションの原子性(「すべて成功」か「すべて失敗」のどちらか)が崩れた状態になる可能性があります。 XAリソースの場合

XAリソースの場合、プリペア処理で「書き込み1」でコミットできないことを検知し、たとえ「書き込み2」のプリペア処理が成功しても、トランザクション処理全体をロールバックさせます。 そのため非XAリソースで発生したトランザクションの原子性を保つことができます。
以上のような理由から、複数のリソースにまたがるグローバルトランザクション処理を作成する場合、2フェーズコミットをサポートしているXAリソースの使用を推奨しています。

ファイル系アダプタのトランザクション

ファイル系アダプタの書き込み処理のトランザクション処理は以下の流れで実装されています。
  1. トランザクション開始
  2. テンポラリファイルへの書き込み
  3. 指定された書き込み先がトランザクション開始時から更新されていないかどうかのチェック
    →更新されていた場合には「XAException」が発生し、トランザクション処理が失敗します。
  4. テンポラリファイルから指定された書き込み先へコピーを行い、テンポラリファイルを削除(コミット時)
    →アダプタで指定された書き込み先ファイルが更新される
  5. テンポラリファイルの削除(ロールバック時)
    →アダプタで指定された書き込み先ファイルは更新されない
ファイル系アダプタの書き込み処理は、デフォルトではスクリプトのトランザクション属性に関わらずトランザクション処理を行いません。
トランザクション処理を行うためには、[トランザクション]タブの[トランザクション処理を行う]にチェックを入れてください。
トランザクション処理を有効にし、スクリプトがトランザクションに参加している場合にはそのトランザクションに参加し、スクリプトがトランザクションに参加していない場合にはコンポーネント単位でのトランザクション処理になります。
ファイル系アダプタの書き込み処理でトランザクション参加時に、書き込み先のディレクトリに書き込み権限がない、ネットワークの寸断などでコミットに失敗した場合にはロールバックが行われません。