28 トランザクション・ガードの使用

トランザクション・ガードは、計画済および計画外の停止の場合に、実行を最大1回にするためにアプリケーションで使用される汎用ツールを提供します。アプリケーションでは論理トランザクションIDを使用して、停止に続くデータベース・セッション内でオープンになっている最終トランザクションのコミット結果が判断されます。トランザクション・ガードを使用しないと、アプリケーションが停止の後にリプレイ操作を実行しようとして、トランザクションが重複してコミットされ論理破損が発生する可能性があります。トランザクション・ガードは、自動で透過的にトランザクションをリプレイするために、アプリケーション・コンティニュイティによって使用されます。

トランザクション・ガードには次のような利点があります。

  • 返された結果を維持します - コミット済か未コミットかにかかわらず、その結果を信頼できるようになります

  • すべてのトランザクションで既知のコミット結果を保証

  • 再送信が必要なアプリケーションに対して、最大1回のトランザクションを実行するために使用できます

  • 自動で透過的にトランザクションをリプレイするために、アプリケーション・コンティニュイティによって使用されます

この章は、トランザクション・ガードを使用するテクノロジまたは製品環境に関連する主な概念および技術をよく理解していることを前提としています。

トピック:

関連項目:

  • トランザクション・ガードとともにOracle Java Database Connectivity (JDBC)を使用する方法の詳細は、『Oracle Database JDBC開発者ガイド』を参照してください

  • OCIとトランザクション・ガードの使用方法の詳細は、『Oracle Call Interfaceプログラマーズ・ガイド』を参照してください

トランザクション・ガードが解決する問題

トランザクション・ガードがないアプリケーションの場合、停止後にアプリケーションをリカバリする際の根本的問題が、クライアントに返送されたコミット・メッセージに継続性がないことです。クライアントとサーバー間に間隔がある場合、クライアントには通信の失敗というエラー・メッセージが示されます。このエラーでは次のことがアプリケーションに知らされません。すなわち、送信によってコミット操作が実行されたかどうか、もしくは、プロシージャ・コールが予定されたすべてのコミットおよびセッション状態の変更を完了および実行したか、コールが途中で失敗したか、またはクライアントから切断したまま現在も実行中というさらに悪い状態になっているかということです。

トランザクション・ガードがない場合、サーバーに対する通信障害の後、保証されたスケーラブルな方法で最後のコミット操作の結果を確認することが不可能または非常に困難になります。データベースに対する送信がコミットされたかどうかをアプリケーションが判断する必要がある場合は、アプリケーション内で可能性のあるすべてのコミット・ポイントについて結果を問い合せるカスタム例外コードを追加する必要があります。システム内のあらゆる場所で障害が発生する可能性があることを考慮すると、これはほとんど非現実的です。問合せは送信ごとに固有である必要があるためです。アプリケーションが構築されて本番稼働した後では、これは完全に実現不可能です。さらに、この問合せが実行された直後にトランザクションがコミットされる可能性があるため、問合せによって正しい回答を得ることはできません。実際に、通信障害の発生後、サーバーがクライアントが切断されたことに気付かずに、送信をまだ実行中である可能性があります。データベース内のPL/SQLまたはJavaでは、プロシージャ型送信の場合、この送信が完了まで実行されたか途中で中断されたかに関するレコードもありません。このようなプロシージャがコミットされた可能性があると同時に、このプロシージャに対する後続の処理が実行されていない可能性もあります。

最後の送信がコミットされたか、近いうちにコミットされるか、または完了まで実行されていないかを識別できない場合、アプリケーションがリプレイを試みることにより、すでに永続化されている変更の再発行が試みられる可能性があるため、トランザクションの送信が重複し、他の形式の論理的破損が発生する可能性があります。

トランザクション・ガードがない場合、トランザクションが開始されており、コミットが発行されている場合、クライアントに返送されたコミット・メッセージに永続性がありません。クライアントは、トランザクションがコミットされたかどうかを認識しないまま残されます。トランザクションは、非トランザクション状態が不正確な場合、またはすでにコミットされている場合は、有効に再送信できません。コミットの保証または完了情報がない場合、再送信を行うと、トランザクションが複数回、不正な状態のセッションで適用される可能性があります。

トランザクション・ガードが提供するソリューション

Oracle Database 12cリリース1 (12.1.0.1)で有効なトランザクション・ガードによって、自動的かつ透過的に基準化された方法で冪等性を達成するために、アプリケーションで使用される新たな統合ツールが提供されます。主要機能は次のとおりです。

  • データベース(Oracle Database 12cリリース1 (12.1.0.1)以降)でサポートされているすべてのトランザクション・タイプに対して、コミット時に論理トランザクション識別子(LTXID)を保存することにより、COMMIT結果の永続性を実現します。これには、PL/SQL内から、リモート・トランザクション(1フェーズXAトランザクション)内から、および他の方法では汎用的手段を使用して識別できないコールアウトから、自動コミットを使用して実行したトランザクションの冪等性が含まれます。

  • LTXIDを使用することにより、LTXIDによって識別される進行中のトランザクションのコピーが複数存在する場合に、論理トランザクション識別子によって保護されているデータベース・トランザクションを重複できないようにすることなどを目的として、最大1回の実行セマンティクスをサポートします。

  • 停止状況とは関係なく、LTXIDによって保護されている同じトランザクションの別の送信をコミットできないようにするために、進行中の処理のコミットをブロックします。

  • LTXIDでコミットされた処理が最上位コール(クライアントからサーバー)の一部としてコミットされたか、サーバーのプロシージャ(PL/SQLなど)に埋め込まれているかを識別します。埋め込まれたコミット状態とは、コミットは完了しているが、コミットが実行されたプロシージャ全体がまだ完了まで実行されていないことを示します。コミット以降の処理は、そのプロシージャ自体がデータベース・エンジンに戻るまでは完了したことを保証することはできません。

  • コミット解決の対象であるデータベースが元の送信より進んでいるか、同期が取れているか、または遅れているかどうかを識別し、クライアントからのトランザクションの送信順序にギャップがある場合は拒否します。サーバーまたはクライアントがLTXIDの順序と同期が取れていないときに結果を取得しようとすると、エラーとみなされます。

  • LTXIDが変更されると、JDBC Thinクライアント・ドライバでコールバックが起動されます。これは、WebLogic Serverやサード・パーティなどの上位レイヤーのアプリケーションが、使用可能な現在のLTXIDを必要に応じて保持するために使用できます。

  • グローバルに分散したデータベースやインフラストラクチャに統合されるデータベース全体にわたってネームスペースの一意性を確保します。これには、Oracle Real Application Clusters (Oracle RAC)とRAC One、Data Guardが含まれます。

  • Multitenantインフラストラクチャに統合されるグローバル・データベースおよびデータベース全体にわたってサービス名の一意性を確保します。これにより、接続がトランザクション情報に正しく転送されます。

トランザクション・ガードの概念および範囲

この項では、トランザクション・ガードに関する主な概念、およびトランザクション・ガードが網羅する内容と網羅しない内容について説明します。

トピック:

関連項目:

  • トランザクション・ガードの処理の詳細は、『Oracle Database概要』を参照してください

  • トランザクション・ガードとともにOracle Java Database Connectivity (JDBC)を使用する方法の詳細は、『Oracle Database JDBC開発者ガイド』を参照してください

論理トランザクション識別子(LTXID)

アプリケーションでは論理トランザクションID (LTXID)という概念を使用して、停止に続くデータベース・セッション内でオープンになっている最終トランザクションの結果が判断されます。論理トランザクションIDは、OCIセッション・ハンドル内、およびJDBC ThinドライバとODP.NETドライバの接続オブジェクト内に格納されます。論理トランザクションIDは、最大1回セマンティクスの基礎となります。

トランザクション・ガードプロトコルにより、次が保証されます。

  • 各論理トランザクションの実行が一意になります。

  • サポートされているコミット時に重複を検出することにより、すべてのコミット・ポイントにおいてプロトコルが回避されないようにする必要があります。

  • トランザクションがコミットされると、再試行の保存期間中は論理トランザクションIDが永続化されます(デフォルト = 24時間、最大 = 30日)。

  • 結果を取得するとき、LTXIDをブロックすることにより、そのLTXIDの以前の進行中のバージョンをコミットできなくし、未コミット・ステータスを強制します。LTXIDが同じである以前のバージョンがすでにコミットまたは強制されている場合、LTXIDをブロックすると、同じ結果が得られます。

論理セッション番号はセッションの確立時に自動的に割り当てられます。これは、アプリケーションが読み取ることができない不透明な構造です。スケーラビリティを確保するために、各LTXIDにはコミット番号と呼ばれる実行番号があります。これは、データベースに対するラウンド・トリップごとにデータベース・トランザクションがコミットされると、増分されます。この実行コミット番号はゼロベースです。

最大1回の実行

トランザクション・ガードは、論理トランザクション識別子(LTXID)を使用してトランザクションの重複を回避します。トランザクションの最大1回の実行を保証するこの機能は、トランザクションの冪等性と呼ばれます。LTXIDはコミット時に継続され、ロールバックの後に再利用されます。通常の実行中、LTXIDは、各データベース・トランザクションについてクライアントおよびサーバーの両方で自動的にセッションで保持されます。コミット時には、LTXIDはトランザクションのコミットの一部として永続化されます。

最大1回プロトコルでは、リプレイについて合意した保存期間中はデータベースがLTXIDを保持することが必要になります。デフォルトの保存期間は24時間ですが、これより短いまたは長い期間が必要な場合もあり、1週間以上になることも考えられます。保存期間が長くなるほど、最大1回チェックにより、LTXIDを使用した古いトランザクションのリプレイがブロックされる期間が長くなります。この設定はサービスごとに使用できます。Data GuardやActive Data Guardを使用する場合など、複数のデータベースが関連する場合、REDOの使用を介して関連するデータベースごとにLTXIDがレプリケートされます。

Oracle JDBC Thin (OCI、OCCIおよびODP.NETクライアント用として類似するAPIがあります)用として提供されているgetLTXID APIにより、アプリケーションはデッド・セッションで使用されていた論理トランザクション識別子を取得できるようになります。これは、この最後のトランザクションのステータスを確認するために必要になります。

DBMS_APP_CONT.GET_LTXID_OUTCOME PL/SQLサブプログラムを使用すると、アプリケーションで、指定された論理トランザクション識別子のアクションの結果を検索できます。DBMS_APP_CONT.GET_LTXID_OUTCOMEのコールには、結果が判明するようにLTXIDのコミットをブロックするサーバーが関わる場合があります。これは、このLTXIDを使用するトランザクションが進行中であるかコミットしようとしている場合の必要条件になります。トランザクション・ガードを使用するアプリケーションは、リカバリ可能なエラーの後にLTXIDを取得してから、リプレイを試行する前にDBMS_APP_CONT.GET_LTXID_OUTCOMEをコールします。

関連項目:

DBMS_APP_CONT.GET_LTXID_OUTCOME PL/SQLサブプログラムの詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。

トランザクション・ガードのカバレッジ

注意:

マルチテナント・コンテナ・データベースは、Oracle Database 20cでサポートされる唯一のアーキテクチャです。ドキュメントが改訂されている間は、従来の用語が残っている可能性があります。ほとんどの場合、「データベース」と「非CDB」は、コンテキストに応じてCDBまたはPDBを指しています。アップグレードなどのコンテキストでは、「非CDB」が以前のリリースの非CDBを指す場合もあります。

システム内の各データベースでトランザクション・ガードを使用できます。これには、単一インスタンス・データベース、Real Application Clusters、Data GuardおよびActive Data Guard間の再起動やフェイルオーバーが含まれます。

トランザクション・ガードは、次に示すOracle Database 12cの構成でサポートされます。

  • 単一インスタンスのOracle RDBMS

  • Real Application Clusters

  • Data Guard

  • Active Data Guard

  • Multitenant: PDB/CDBの切断/接続を含む(12.2の場合はPDB/CDB全体に再配置しますが、"with clone"オプションを除く)

  • 前述のデータベース構成用のグローバル・データ・サービス

トランザクション・ガードはOracle Database 12cに対して、次に示すのトランザクション・タイプをサポートしています。

  • ローカル・トランザクション

  • データ定義言語(DDL)トランザクション

  • データ制御言語(DCL)トランザクション

  • 分散トランザクション

  • リモート・トランザクション

  • パラレル・トランザクション

  • 成功時のコミット(自動コミット)

  • 埋込みコミットがサポートされているクライアント・ドライバを使用したPL/SQL

  • Oracle Database 12c リリース2 (12.2.0.1)以降、One Phase Optimizationsを使用するXAトランザクション(XAコミット・フラグのTMONEPHASEおよび読取り最適化を含む)

  • サービス句を指定したALTER SESSION SETコンテナ(このサービスはトランザクション・ガードを使用)

トランザクション・ガードは、次に示すクライアント・ドライバをサポートしています。

  • 12c JDBCタイプ4ドライバ

  • 12c OCIおよびOCCIクライアント・ドライバ

  • 12c Oracle Data Provider for .NET (ODP.NET)、管理対象外ドライバ

  • 12c ODP.NET、ODAC 12c リリース4以降の管理対象ドライバ

トランザクション・ガードとXAトランザクション

Oracle Database 12.2 リリース以降、トランザクション・ガードでは1フェーズ・トランザクションの結果を判別するために、XAトランザクションをサポートしています。トランザクション・ガードは、commitの操作中にTMONEPHASEを使用するローカル・トランザクションとXAトランザクションをサポートします。アプリケーションがTMTWOPHASEを使用するXAトランザクションを発行すると、トランザクション・ガードはそのトランザクションのために自らを無効にします。その後、自動的に次のトランザクションに向けて、再度有効にします。これにより、トランザクション・ガードは次に示すXAトランザクションをサポートできます。

  1. autocommitを使用するローカル・トランザクション

  2. 明示的なcommitを使用するローカル・トランザクション

  3. TMONEPHASEフラグを使用してコミットするXAトランザクション

TPモニターとアプリケーションでは、トランザクション・ガードを使用して、commit操作の結果を取得できます。トランザクション・ガードは外部管理のTMTWOPHASEコミット操作のために自らを無効にし、その後、次のトランザクションのために自動的に再度有効にします。トランザクション・ガードAPIがTMTWOPHASEトランザクションで使用されると、トランザクションガードが無効になっているため、警告メッセージが返されます。TPモニターは、TMTWOPHASEトランザクションのコミット結果を所有します。この機能により、TPモニターはTMONEPHASE操作の明確な結果を返すことができます。

トランザクション・ガードの除外

トランザクション・ガードは、再帰的トランザクションおよび自律型トランザクションを意図的に除外することにより、これらを再実行できるようにします。

Oracle Database 12cリリース2では、トランザクション・ガードで次の機能も除外されます。

  • 2フェーズXAトランザクションは外部で管理されます。XAトランザクションを使用する場合、トランザクション・ガードは1フェーズXAトランザクションのコミット結果を維持しますが、外部管理された2フェーズトランザクションの場合は結果をTPモニターが所有するため、暗黙的に自らを無効にします。

  • 転送トランザクション用の読取り/書込みデータベース・リンクのあるActive Data Guard

  • 論理データベース間で失敗する場合に結果を判別するGolden Gateおよびロジカル・スタンバイ。Golden Gateおよびロジカル・スタンバイ・エンドポイントはトランザクション・ガードを使用できます

  • トランザクション・ガードが有効な場合、完全なデータベースのインポートは実行できません。完全なデータベースのインポートには、トランザクション・ガードを使用しない管理サービスを使用します。ユーザーとオブジェクトのインポートは除外されません。

  • TAFとアプリケーション・コンティニュイティは、トランザクション・ガードを内部的に処理します。次の場所では、トランザクション・ガードをアプリケーションでコード化しないでください。
    • 失敗したTAFからの復帰

    • TAFコールバック(TAF、またはOCIおよびODP.NETのアプリケーション・コンティニュイティ向け)

    • Javaのアプリケーション・コンティニュイティ向けのJDBC初期化コールバック

トランザクション・ガードは、レプリケーション・テクノロジによって維持されるデータベース全体のフェイルオーバーを除外します。

  • Golden Gateへのレプリケーション

  • ロジカル・スタンバイへのレプリケーション

  •  PDBクローン句(12c リリース2以降のPDBのオンラインでの再配置を除く)

  • すべてのサード・パーティのレプリケーション・ソリューション

Golden Gate、Logical Standbyまたはサード・パーティ・レプリケーションなどのレプリケーション・テクノロジを使用してデータベースのレプリカを使用している場合、この構成ではプライマリ・データベースとセカンダリ・データベース間でトランザクション・ガードを使用できない可能性があります。

トランザクション・ガードは、レプリケーションに関与する各データベースで使用できます。この場合、各データベースでは、異なるデータベース固有の識別子を使用する必要があります。V$DATABASEを使用して、各データベースのDBIDを取得します。

トランザクション・ガードのデータベース構成

この項には、トランザクション・ガードを使用するためのデータベースの構成に関する情報が含まれます。

トピック:

構成チェックリスト

アプリケーションとともにトランザクション・ガードを使用するには、次を実行する必要があります。

  • Oracle Database 12cリリース1 (12.1.0.1)以降を使用します。

  • すべてのデータベース処理に対してアプリケーション・サービスを使用します。Oracle RACを使用している場合はsrvctlコマンドを使用して、またはOracle RACを使用していない場合はDBMS_SERVICE.CREATE_SERVICE PL/SQLサブプログラムを使用してサービスを作成します。

    デフォルト・データベース・サービスは使用しないでください。これらのサービスは管理用であり、操作できません。つまり、db_nameまたはdb_unique_nameに設定されているサービス名は使用しないでください。

  • DBMS_APP_CONTパッケージに対する権限を、GET_LTXID_OUTCOMEをコールするデータベース・ユーザーに付与します。

    GRANT EXECUTE ON DBMS_APP_CONT TO <user-name>;
    
  • トランザクション・ガードをDDL文で使用する場合は、DDL_LOCK_TIMEOUTを増やします。

アプリケーションとともにトランザクション・ガードを使用するには、次を実行することをお薦めします。

  • 最適なパフォーマンスを実現するためにトランザクション履歴表を特定および定義します。

  • Oracle RACまたはOracle Data Guardを使用している場合、エラー時に通信してクライアントをすぐに中断できるように、FANが構成されていることを確認します。

  • 次のパラメータを設定します: AQ_HA_NOTIFICATIONS = TRUE (OCI FANを使用している場合)。

関連項目:

トランザクション履歴表

トランザクション履歴表は、論理トランザクション識別子(LTXID)からデータベース・トランザクションへのマッピングを保持します。この表にアクセスできるのは、DBA権限を持つデータベース・ユーザーのみです。これはOracle Databaseによって自動的に保持されるため、トランザクション履歴表に対してDDLまたはDML文を直接発行しないでください。

デフォルトでは、トランザクション履歴表(LTXID_TRANS)は、データベースの作成およびアップグレード時にSYSAUX表領域に作成されます。最後のパーティションの記憶域を使用して、インスタンスの追加時に新規パーティションが追加されます。ただし、この表領域の場所がパフォーマンスに最適ではない場合、DBAはパーティションを別の表領域に移動できます。たとえば、次の文を使用すると、トランザクション履歴表が変更され、FastPaceという名前の表領域に移動されます。

ALTER TABLE LTXID_TRANS move partition LTXID_TRANS_4
 tablespace FastPace
 storage ( initial 10G next 10G
 minextents 1 maxextents 121 );

関連項目:

  • ALTER TABLE文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください

サービス・パラメータ

コミットの結果および保存用のサービスを構成します。

例:

COMMIT_OUTCOME = TRUE
RETENTION_TIMEOUT = <retention-value>

COMMIT_OUTCOMEは、コミットが実行された後にトランザクションのコミット結果にアクセスできるかどうかを確認します。この機能は、コミットの結果を永続化します。この機能は、停止前に実行された最後のトランザクションのステータスを強制するためにアプリケーションによって使用されます。この機能は、Oracleリプレイ・ドライバおよびWebLogic Serverによって内部的に使用され、他のアプリケーションが結果を確認するために使用することもできます。COMMIT_OUTCOMEで使用可能な値はFALSE (デフォルト)およびTRUEであり、トランザクション・ガードを有効に使用するにはこの値をTRUEに設定する必要があります。

COMMIT_OUTCOMEについて考慮する必要がある事項は次のとおりです。

  • DBMS_APP_CONT.GET_LTXID_OUTCOMEプロシージャを使用するには、COMMIT_OUTCOMETRUEに設定する必要があります。

  • COMMIT_OUTCOMEは、Active Data Guardおよび読取り専用データベースに対しては効果がありません。トランザクション・ガードと、DMLを転送するデータベース・リンクと組み合せた読取り/書込みActive Data Guardの併用はサポートされていません。

  • COMMIT_OUTCOMEは、ユーザー定義データベース・サービスで許可されます。データベース・サービスでの使用は除外されます。このサービスはData Guardでは切り替わらず、プライマリ・データベースでの計画済停止に対して開始、停止または無効化できないためです。

RETENTION_TIMEOUTは、コミット結果が保存される合計時間を設定するためにCOMMIT_OUTCOMEとともに使用されます。保存タイムアウト値は秒単位で指定します。デフォルトは86400 (24時間)、最大は2592000 (30日)です。srvctlコマンドまたはDBMS_SERVICE PL/SQLパッケージを使用して、保存タイムアウト値を指定できます。

関連項目:

例: サーバー・プール用のサービスの追加および変更

Oracle RACまたはOracle RAC Oneを使用している場合、srvctlコマンドを使用してサービスを作成および変更します。

例28-1には、srvctlの使用方法を示します。Global Data Services (GDSCTL)も使用できます。

例28-1 サーバー・プール用のサービスの追加および変更

srvctl add service -database orcl -service GOLD -poolname ora.Srvpool  -commit_outcome TRUE  -retention 604800
srvctl modify service -database orcl -service GOLD -commit_outcome TRUE  -retention 604800
例: 管理者管理サービスの追加

Oracle RACまたはOracle RAC Oneを使用している場合、srvctlコマンドを使用してサービスを作成および変更します。

例28-2には、srvctlの使用方法を示します。Global Data Services (GDSCTL)も使用できます

例28-2 管理者管理サービスの追加

srvctl add service -database codedb -service GOLD -preferred serv1 -available serv2 -commit_outcome TRUE  -retention 604800
例: サービスの変更(PL/SQL)

単一インスタンス・データベースを使用している場合、DBMS_SERVICE.MODIFY_SERVICE PL/SQLプロシージャを使用してサービスを変更し、FANを使用します。

例28-3では、サービスを変更します(ただし、<service-name>は実際のサービス名に変更します)。

例28-3 サービスの変更(PL/SQL)


DECLARE
  params dbms_service.svc_parameter_array;
BEGIN
  params('COMMIT_OUTCOME'):='true';
  params('RETENTION_TIMEOUT'):=604800;
  params('aq_ha_notifications'):='true';
  dbms_service.modify_service('<service-name>',params);
END;
/

トランザクション・ガードを使用するアプリケーションの開発

トランザクション・ガードを使用するには、「構成チェックリスト」の要件と推奨事項を確認します。また、リカバリ可能なエラーが発生した場合には次のエラー処理のステップに従います。

  1. エラーがリカバリ可能なエラーであり、データベース・セッションが使用不可になっていることを調べます。
  2. クライアント・ドライバ提供のAPI (JDBCにはgetLTXID、OCIにはLTXIDとともにOCI_ATTR_GET、およびODP.NETにはLogicalTransactionId)を使用して、前に失敗したセッションからLTXIDを取得します。
  3. 新規セッションをそのセッションの独自LTXIDとともに取得します。
  4. APIから取得したLTXIDを使用してDBMS_APP_CONT.GET_LTXID_OUTCOME PL/SQLプロシージャを起動します。戻り状態により、ドライバは最後のトランザクションがCOMMITTED (TRUE/FALSE)およびUSER_CALL_COMPLETED (TRUE/FALSE)であったことを確認します。クライアントとデータベースが同期していないと、このPL/SQLファンクションによってエラーが返されます(たとえば、同じデータベースでない場合またはデータベースがリストアされた場合)。
  5. アプリケーションが結果を戻して、ユーザーが判別できます。アプリケーションは自動的にリプレイできます。リプレイ自体によって停止する場合は、リプレイ・セッションのLTXIDがDBMS_APP_CONT.GET_LTXID_OUTCOMEプロシージャに使用されます。

典型的なトランザクション・ガードの使用例

次の疑似コードは、トランザクション・ガードの標準使用例です。

Receive a FAN down event (or recoverable error)
 
FAN aborts the dead session
 
If recoverable error  (new OCI_ATTRIBUTE for OCI, isRecoverable for JDBC)
     Get last LTXID from dead session using getLTXID or from your callback
     Obtain a new session 
     Call GET_LTXID_OUTCOME with last LTXID to obtain COMMITTED and USER_CALL_COMPLETED status
 
If COMMITTED and USER_CALL_COMPLETED  
     Then return result
 
ELSEIF COMMITTED and NOT USER_CALL_COMPLETED   
     Then return result with a warning (that details such as out binds or row count were not returned)
 
ELSEIF NOT COMMITTED 
     Cleanup and resubmit request, or return uncommitted result to the client

LTXIDの使用の詳細

リプレイおよび戻り結果を得るには、アプリケーションまたはサード・パーティ・コンテナが、セッションごとにサーバーでコミットされる次のLTXIDにアクセスできる必要があります。LTXIDは、リカバリ可能な停止後に失敗したセッションからAPI (JDBCにはgetLTXID、およびOCIにはLTXIDとともにOCI_ATTR_GET)を使用して取得できます。

JDBC Thinドライバには、データベースから取得したコミット番号変更ごとに実行されるコールバックが用意されています。サード・パーティ・コンテナは、このコールバックを使用して、フェイルオーバーが必要な際の使用に備えて現在のLTXIDを保存できます。各セッションでは現在のLTXIDが使用中であるため、コールバックは以前のLTXIDをオーバーライドできます。

フェイルオーバーが完了せずにカスケード(つまり、1つの障害からのリカバリ時に別の障害が発生)する場合、アプリケーションは、現在のセッションで有効なLTXIDを取得してGET_LTXID_OUTCOMEに渡す必要があります

表28-1は、LTXID関連のアクションが必要な状態または状況、そのアプリケーション・アクション、および次に使用するLTXIDをそれぞれ示しています。

表28-1 LTXIDの状態または状況、アプリケーション・アクション、および次に使用するLTXID

状態および状況 アプリケーションのアクション 次に使用するLTXID (コンテナのLTXID変更に対するコールバック - JDBC Thinのみ)

アプリケーションが、リカバリ可能なエラーを受信し、GET_LTXID_OUTCOMEをコールしてトランザクション・ステータスを確認します。

アプリケーションは、新規接続を確立し(独自のLTXID-B 0を使用)、最後に失敗したセッションのLTXID (LTXID-A)を使用してGET_LTXID_OUTCOMEをコールします。

新規LTXID-B 0

登録時にもJDBCコールバックを使用して設定します

アプリケーションが、最後のセッション・トランザクション・ステータスがCOMMITTEDおよびUSER_CALL_COMPLETEDであることを確認します。

コミット済ステータスをクライアントに戻すと、アプリケーションを続行できます。

(該当なし)

アプリケーションが、最後のセッション・トランザクション・ステータスがCOMMITTEDであり、USER_CALL_COMPLETEDでないことを確認します。

コミット済ステータスをクライアントに戻し、終了します。コール内の処理が完了していないため(たとえば、OUTバインドまたは行カウントが戻されなかった)、一部のアプリケーションは続行できません。アプリケーションが続行可能かどうかは、アプリケーションに依存します。

(該当なし)

アプリケーションで、最後のセッション・トランザクション・ステータスがNOT COMMITTEDであることを確認します。

アプリケーションが結果をユーザーに返すか、必要であればクリーンアップし、有効な新セッションのLTXID (LTXID-B 0)を使用して再発行します。

新規リクエストによってコミットが実行されると、サーバーはLTXID-B 2以上のコミット・メッセージを戻します。

新規LTXID-B 2 ..N

登録時にもJDBCコールバックを使用して設定します

アプリケーションがリプレイを決定した場合、リカバリ可能なエラーを受信します。

アプリケーションは、新規接続を確立し(独自のLTXID-C 0を使用)、最後のセッションのLTXID (LTXID-B N)を使用してGET_LTXID_OUTCOMEをコールします。

新規セッションのLTXID-C 0。

登録時にもJDBCコールバックを使用して設定します

アプリケーションがリプレイを決定した場合、もう1つのリカバリ可能なエラーを受信します。

アプリケーションは、新規接続を確立し(独自のLTXID-D 0を使用)、最後のセッションのLTXID (LTXID-C N)を使用してGET_LTXID_OUTCOMEをコールします。

新規セッションのLTXID-D 0。

登録時にもJDBCコールバックを使用して設定します

トランザクション・ガードと透過的アプリケーション・フェイルオーバー

トランザクション・ガードで透過的アプリケーション・フェイルオーバー(TAF)が有効になっている場合、TAFは開発者のエラーを処理します。TAFを使用しているときはトランザクション・ガードをコード化しないでください。Oracle Database 12c リリース1 (12.1.0.1)以降には、トランザクション・ガードのコードが組み込まれているためです。TAFとトランザクション・ガードの両方を使用する場合、開発者は次のTAFエラーを使用して、ロールバック、安全な再発行またはコミットされていない状態への復帰を実行できます。

  • ORA-25402

  • ORA-25408

  • ORA-25405

開発者はTAFが有効なときに、GET_LTXID_OUTCOMEプロシージャを直接使用しないでください。これは、TAFがすでにトランザクション・ガードの処理を行っているためです。

注意:

TAFはセッションの失敗時には呼び出されません(これには、オペレーティング・システム・レベルの"kill -9"またはALTER SYSTEM KILLセッションが含まれます)。TAFは、次に示す状態で呼び出されます。

  • INSTANCE失敗

  • FAN NODE DOWNイベント

  • SHUTDOWNトランザクション

  • POST_TRANSACTION切断

ODP.NETでのトランザクション・ガードの使用

ODP.NETでトランザクション・ガードを使用する場合、次のルールが適用されます。

  • 両方のODP.NETプロバイダでXAに昇格した後は、LTXIDを使用できません。

  • Oracle Database 12c リリース2 (12.2.0.1)以降では、ODP.NETはそれ自体の可用性と処理能力に基づいて、アプリケーションのトランザクション・ガードを処理します。ODP.NETを使用する場合、ODP.NETがアプリケーションのかわりにコミット結果を取得できない場合にのみ、LTXIDがアプリケーションに公開されます。たとえば、Data Guardへのフェイルオーバー時などです。

  • 開発者は、TAFコールバックまたはJDBC初期化コールバックで、トランザクション・ガードをコード化しないでください。トランザクション・ガードはユーザーのために処理されます。

接続プールLTXIDの使用

接続プールは、LTXIDを管理するために別のユースケースを作成します。これは、接続およびセッションが事前に確立されて共有されるためです。接続プールおよび中間層の最も簡単なモデルでは、LTXIDはセッション・ハンドル(クライアント側のセッション)ごとに存在します。これは、接続プールからチェックアウトされる際にアプリケーション・リクエストに関連付けられ、プールにチェックインして戻される際にアプリケーション・リクエストから切断されます。チェックアウトとチェックインの間、セッションのLTXIDはこのアプリケーション・リクエストによって排他的に保持されます。チェックイン後、LTXIDはアイドル状態のプール・セッションに属します。これは、接続をチェックアウトする次のアプリケーション・リクエストに関連付けられます。

トランザクション・ガードをこの方法で使用する場合:

  • 現在のHTTPリクエストに関する重複の検出およびフェイルオーバーをサポートできます

  • タイムアウトしたリクエストや、アプリケーションによる任意の再送信を取り消すことができます(実際のCancel操作。[Ctrl]+[C]ではありません)。

XA 1フェーズ最適化のコミット結果の向上

Oracle Database 12c リリース2 (12.2.0.1)以降では、トランザクション・ガードとトランザクション処理モニター(TPM)を併用して、1フェーズ最適化(TMONEPLHASEフラグ)の使用時に、コミット操作の結果を判断します。トランザクション・ガードはGET_LTXID_OUTCOMEパッケージを使用して、リソースマネージャへの接続が失われたかどうかや、あいまいなエラーが返されたかどうかをTPMが判断できるようにします。

表28-2 トランザクション・マネージャの状態/状況およびアクション

状態および状況 トランザクション・マネージャのアクション

Commitが発行されず、トランザクションがロールバックされている場合。

トランザクション・マネージャはrollbackを返します。

Commitが発行され、あいまいな結果が返された場合。

トランザクション・マネージャはエラーがリカバリ可能な場合に、トランザクション・ガード(XA)を使用して結果を判断できます。

トランザクションがCOMMITTEDの場合。

トランザクション・マネージャはCOMMITTEDを返します。

トランザクションがUNCOMMITTEDの場合。

トランザクション・マネージャは新しい接続を流用して、COMMITを再発行します。元のLTXIDは、GET_LTXID_OUTCOMEをコールすることでブロックされます。

トランザクション・ガード開発の追加要件

トランザクション・ガードは、開発者がリカバリ可能なエラー後に使用し、既知の結果を提供するためのツールです。これは、最後のセッションがデッド状態であることを示すエラーが戻されたときに使用する必要があります。

次の場合、トランザクション・ガードAPIは使用しないでください

  • 現在のセッションでGET_LTXID_OUTCOMEを使用しないでください。エラーが戻されます。

  • リカバリ可能なエラーを受信しなかったセッション(つまり、ライブ・セッション)でGET_LTXID_OUTCOMEを使用しないでください。このセッションのコミットはブロックされます。

  • 別のユーザーから、または別のデータベースに対して、GET_LTXID_OUTCOMEを使用しないでください。エラーが戻されます。

  • 即時使用するのではなく、後で使用する場合はLTXIDを取得および保存しないでください。GET_LTXID_OUTCOMEの結果が有効なのは、最後のオープン・トランザクションまたは完了したトランザクションに対してのみです。同じセッションで以前のトランザクションとともに使用すると、エラーが戻されます。

  • アプリケーションがTAFを使用している場合は、トランザクション・ガードをコード化しないでください。かわりに新しいTAFエラーコードを使用して、結果を返します。

    注意:

    このルールはアプリケーション・コンティニュイティには適用できません。

トランザクション・ガードおよびアプリケーション・コンティニュイティとの関係

トランザクション・ガードには、データベース・トランザクションごとに一意の識別子(LTXID)が用意されています。この識別子は、トランザクションのコミット結果を問い合せるために使用したり、トランザクションが1回のみ適用されるようにするために使用できます。トランザクション・ガードはアプリケーション・コンティニュイティによって使用され、これによって自動的に有効化されますが、独立して有効化することもできます。トランザクション・ガードは、アプリケーション・コンティニュイティがリプレイするトランザクションが複数回適用されるのを阻止します。アプリケーションがアプリケーション・レベルのリプレイを実装した場合、冪等性を実現するためにアプリケーションをトランザクション・ガードと統合する必要があります。

コード化を必要としないソリューションの場合は、アプリケーション・コンティニュイティを使用するようにアプリケーションを構成します。独自のリプレイを開発する場合、アプリケーション開発者はトランザクション・ガードを使用してコード化を行います。アプリケーションは、トランザクション・ガードとアプリケーション・コンティニュイティの両方に向けてコード化できます。まず、アプリケーション・コンティニュイティに効果が現れます。アプリケーション・コンティニュイティがリプレイできない場合にのみ、カスタムのトランザクション・ガードのコードに効果が現れます。両方を使用する必要はありませんが、アプリケーションがトランザクション・ガードとアプリケーション・コンティニュイティの両方を使用する場合は互換性があります。アプリケーション・コンティニュイティに加えて、トランザクション・ガードAPIもアプリケーションに追加すると、トランザクション・ガードはリプレイが無効になった場合や失敗した場合にコミット結果を返すことができます。

関連項目: