トランザクション・ガードは、計画済および計画外の停止の場合に、実行を最大1回にするためにアプリケーションで使用される汎用ツールを提供します。アプリケーションでは論理トランザクションIDを使用して、停止に続くデータベース・セッション内でオープンになっている最終トランザクションの結果が判断されます。トランザクション・ガードを使用しないと、アプリケーションが停止の後にリプレイ操作を実行しようとして、トランザクションが重複してコミットされ論理破損が発生する可能性があります。
トランザクション・ガードには次のような利点があります。
コミット結果の保持
すべてのトランザクションで既知の結果を保証
最大1回のトランザクション実行を実現するために使用可能
この章は、トランザクション・ガードを使用するテクノロジまたは製品環境に関連する主な概念および技術をよく理解していることを前提としています。
内容は次のとおりです。
参照:
|
トランザクション・ガードがないアプリケーションの場合、停止後にアプリケーションをリカバリする際の根本的問題が、クライアントに返送されたコミット・メッセージに継続性がないことです。クライアントとサーバー間に間隔がある場合、クライアントには通信の失敗というエラー・メッセージが示されます。このエラーでは次のことがアプリケーションに知らされません。すなわち、送信によってコミット操作が実行されたかどうか、もしくは、プロシージャ・コールが予定されたすべてのコミットおよびセッション状態の変更を完了および実行したか、コールが途中で失敗したか、またはクライアントから切断したまま現在も実行中というさらに悪い状態になっているかということです。
トランザクション・ガードがない場合、サーバーに対する通信障害の後、保証されたスケーラブルな方法で最後のコミット操作の結果を確認することが不可能または非常に困難になります。データベースに対する送信がコミットされたかどうかをアプリケーションが判断する必要がある場合は、アプリケーション内で可能性のあるすべてのコミット・ポイントについて結果を問い合せるカスタム例外コードを追加する必要があります。システム内のあらゆる場所で障害が発生する可能性があることを考慮すると、これはほとんど非現実的です。問合せは送信ごとに固有である必要があるためです。アプリケーションが構築されて本番稼働した後では、これは完全に実現不可能です。さらに、この問合せが実行された直後にトランザクションがコミットされる可能性があるため、問合せによって正しい回答を得ることはできません。実際に、通信障害の発生後、サーバーがクライアントが切断されたことに気付かずに、送信をまだ実行中である可能性があります。データベース内のPL/SQLまたはJavaでは、プロシージャ型送信の場合、この送信が完了まで実行されたか途中で中断されたかに関するレコードもありません。このようなプロシージャがコミットされた可能性があると同時に、このプロシージャに対する後続の処理が実行されていない可能性もあります。
最後の送信がコミットされたか、近いうちにコミットされるか、または完了まで実行されていないかを識別できない場合、アプリケーションがリプレイを試みることにより、すでに永続化されている変更の再発行が試みられる可能性があるため、トランザクションの送信が重複し、他の形式の論理的破損が発生する可能性があります。
トランザクション・ガードがない場合、トランザクションが開始されており、コミットが発行されている場合、クライアントに返送されたコミット・メッセージに永続性がありません。クライアントは、トランザクションがコミットされたかどうかを認識しないまま残されます。トランザクションは、非トランザクション状態が不正確な場合、またはすでにコミットされている場合は、有効に再送信できません。コミットの保証または完了情報がない場合、再送信を行うと、トランザクションが複数回、不正な状態のセッションで適用される可能性があります。
Oracle Database 12cリリース1 (12.1.0.1)で有効なトランザクション・ガードによって、自動的かつ透過的に基準化された方法で冪等性を達成するために、アプリケーションで使用される新たな統合ツールが提供されます。主要機能は次のとおりです。
データベース(Oracle Database 12cリリース1 (12.1.0.1)以降)でサポートされているすべてのトランザクション・タイプに対して、コミット時に論理トランザクション識別子(LTXID)を保存することにより、COMMIT
結果の永続性を実現します。これには、PL/SQL内から、リモート・トランザクション内から、および他の方法では汎用的手段を使用して識別できないコールアウトから、自動コミットを使用して実行したトランザクションの冪等性が含まれます。
LTXIDを使用することにより、LTXIDによって識別される進行中のトランザクションのコピーが複数存在する場合に、論理トランザクション識別子によって保護されているデータベース・トランザクションを重複できないようにすることなどを目的として、最大1回の実行セマンティクスをサポートします。
停止状況とは関係なく、LTXIDによって保護されている同じトランザクションの別の送信をコミットできないようにするために、進行中の処理のコミットをブロックします。
LTXIDでコミットされた処理が最上位コール(クライアントからサーバー)の一部としてコミットされたか、サーバーのプロシージャ(PL/SQLなど)に埋め込まれているかを識別します。埋め込まれたコミット状態とは、コミットは完了しているが、コミットが実行されたプロシージャ全体がまだ完了まで実行されていないことを示します。コミット以降の処理は、そのプロシージャ自体がデータベース・エンジンに戻るまでは完了したことを保証することはできません。
コミット解決の対象であるデータベースが元の送信より進んでいるか、同期が取れているか、または遅れているかどうかを識別し、クライアントからのトランザクションの送信順序にギャップがある場合は拒否します。サーバーまたはクライアントがLTXIDの順序と同期が取れていないときに結果を取得しようとすると、エラーとみなされます。
LTXIDが変更されると、JDBC Thinクライアント・ドライバでコールバックが起動されます。これは、WebLogic Serverやサード・パーティなどの上位レイヤーのアプリケーションが、使用可能な現在のLTXIDを必要に応じて保持するために使用できます。
グローバルに分散したデータベースやコンテナ(プラガブル)インフラストラクチャに統合されるデータベース全体にわたってネームスペースの一意性を確保します。これには、Oracle Real Application Clusters (Oracle RAC)、Data Guardおよびプラガブル・データベースが含まれます。
コンテナ(プラガブル・データベース)インフラストラクチャに統合されるグローバル・データベースおよびデータベース全体にわたってサービス名の一意性を確保します。これにより、接続がトランザクション情報に正しく転送されます。
この項では、トランザクション・ガードに関する主な概念、およびトランザクション・ガードが網羅する内容と網羅しない内容について説明します。
内容は次のとおりです。
参照:
|
アプリケーションでは論理トランザクションID (LTXID)という概念を使用して、停止に続くデータベース・セッション内でオープンになっている最終トランザクションの結果が判断されます。論理トランザクションIDは、OCIセッション・ハンドル内、およびJDBC ThinドライバとODP.Netドライバの接続オブジェクト内に格納されます。論理トランザクションIDは、最大1回セマンティクスの基礎となります。
トランザクション・ガードプロトコルにより、次が保証されます。
各論理トランザクションの実行が一意になります。
サポートされているコミット時に重複を検出することにより、すべてのコミット・ポイントにおいてプロトコルが回避されないようにする必要があります。
トランザクションがコミットされると、再試行の保存期間中は論理トランザクションIDが永続化されます(デフォルト = 24時間、最大 = 30日)。
結果を取得するとき、LTXIDをブロックすることにより、そのLTXIDの以前の進行中のバージョンをコミットできなくし、未コミット・ステータスを強制します。LTXIDが同じである以前のバージョンがすでにコミットまたは強制されている場合、LTXIDをブロックすると、同じ結果が得られます。
論理セッション番号はセッションの確立時に自動的に割り当てられます。これは、アプリケーションが読み取ることができない不透明な構造です。スケーラビリティを確保するために、各LTXIDにはコミット番号と呼ばれる実行番号があります。これは、データベースに対するラウンド・トリップごとにデータベース・トランザクションがコミットされると、増分されます。この実行コミット番号はゼロベースです。
トランザクション・ガードは、論理トランザクション識別子(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サブプログラム(『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照)により、アプリケーションは特定の論理トランザクション識別子のアクションの結果を検索できるようになります。DBMS_APP_CONT.GET_LTXID_OUTCOME
のコールには、結果が判明するようにLTXIDのコミットをブロックするサーバーが関わる場合があります。これは、このLTXIDを使用するトランザクションが進行中であるかコミットしようとしている場合の必要条件になります。トランザクション・ガードを使用するアプリケーションは、リカバリ可能なエラーの後にLTXIDを取得してから、リプレイを試行する前にDBMS_APP_CONT.GET_LTXID_OUTCOME
をコールします。
トランザクション・ガードは、次のソースからのコミットをサポートしています。
ローカル・トランザクション
データ定義言語(DDL)トランザクション
データ制御言語(DCL)トランザクション
分散トランザクション
リモート・トランザクション
パラレル・トランザクション
成功時のコミット(自動コミット)
埋込みコミットがサポートされているクライアント・ドライバを使用したPL/SQL
サポートされているクライアント・ドライバ:
12c JDBCタイプ4ドライバ
12c OCIおよびOCCIクライアント・ドライバ
12c Oracle Data Provider for .NET (ODP.NET)クライアント・ドライバ
トランザクション・ガードは、再帰的トランザクションおよび自律型トランザクションを意図的に除外することにより、これらをリプレイできるようにします。
Oracle Database 12cリリース1 (12.1.0.1)では、トランザクション・ガードで次の機能も除外されます。
XAトランザクション
転送トランザクション用の読取り/書込みデータベース・リンクのあるActive Data Guard
Golden Gateおよびロジカル・スタンバイ
この項には、トランザクション・ガードを使用するためのデータベースの構成に関する情報が含まれます。
内容は次のとおりです。
アプリケーションとともにトランザクション・ガードを使用するには、次を実行する必要があります。
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>;
アプリケーションとともにトランザクション・ガードを使用するには、次を実行することをお薦めします。
最適なパフォーマンスを実現するためにトランザクション履歴表を特定および定義します。(トランザクション履歴表の詳細は、25.4.2項を参照。)
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 );
参照:
|
コミットの結果および保存用のサービスを構成します。次に例を示します。
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
PL/SQLプロシージャを使用するには、COMMIT_OUTCOME
をTRUE
に設定する必要があります。
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
コマンドを使用してサービスを作成および変更します。例25-1および例25-2は、srvctl
の使用を示しています。Global Data Services (GDSCTL)も使用できます。
例25-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
例25-2 管理者管理サービスの追加
srvctl add service -database codedb -service GOLD -prefer serv1 -available serv2 -commit_outcome TRUE -retention 604800
単一インスタンス・データベースを使用している場合、DBMS_SERVICE.MODIFY_SERVICE
PL/SQLプロシージャを使用してサービスを変更し、FANを使用します。例25-3では、サービスを変更します(ただし、<service-name>は実際のサービス名に変更します)。
例25-3 サービスの変更(PL/SQL)
DECLARE
params dbms_service.svc_parameter_array;
BEGIN
params('COMMIT_OUTCOME'):='true';
params('RETENTION_TIMEOUT'):=604800;
dbms_service.modify_service('<service-name>',params);
END;
/
参照:
|
トランザクション・ガードを使用するには、25.4.1項「構成チェックリスト」の要件と推奨事項を確認します。また、リカバリ可能なエラーが発生した場合には次のエラー処理の手順に従います。
エラーがリカバリ可能なエラーであり、データベース・セッションが使用不可になっていることを調べます。
クライアント・ドライバ提供のAPI (JDBCにはgetLTXID
、OCIにはLTXIDとともにOCI_ATTR_GET
、およびODP.netにはLogicalTransactionId
)を使用して、前に失敗したセッションからLTXIDを取得します。
新規セッションをそのセッションの独自LTXIDとともに取得します。
APIから取得したLTXIDを使用してDBMS_APP_CONT.GET_LTXID_OUTCOME
PL/SQLプロシージャを起動します。戻り状態により、ドライバは最後のトランザクションがCOMMITTED (TRUE/FALSE)
およびUSER_CALL_COMPLETED (TRUE/FALSE)
であったことを確認します。クライアントとデータベースが同期していないと、このPL/SQLファンクションによってエラーが返されます(たとえば、同じデータベースでない場合またはデータベースがリストアされた場合)。
アプリケーションが結果を戻して、ユーザーが判別できます。アプリケーションは自動的にリプレイできます。リプレイ自体によって停止する場合は、リプレイ・セッションの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は、リカバリ可能な停止後に失敗したセッションからAPI (JDBCにはgetLTXID
、およびOCIにはLTXIDとともにOCI_ATTR_GET
)を使用して取得できます。
JDBC Thinドライバには、データベースから取得したコミット番号変更ごとに実行されるコールバックが用意されています。サード・パーティ・コンテナは、このコールバックを使用して、フェイルオーバーが必要な際の使用に備えて現在のLTXIDを保存できます。各セッションでは現在のLTXIDが使用中であるため、コールバックは以前のLTXIDをオーバーライドできます。
フェイルオーバーが完了せずにカスケード(つまり、1つの障害からのリカバリ時に別の障害が発生)する場合、アプリケーションは、現在のセッションで有効なLTXIDを取得してGET_LTXID_OUTCOME
に渡す必要があります。
表25-1は、LTXID関連のアクションが必要な状態または状況、そのアプリケーション・アクション、および次に使用するLTXIDをそれぞれ示しています。
表25-1 LTXIDの状態または状況、アプリケーション・アクション、および次に使用するLTXID
状態および状況 | アプリケーション・アクション | 次に使用するLTXID (コンテナのLTXID変更に対するコールバック - JDBC Thinのみ) |
---|---|---|
アプリケーションが、リカバリ可能なエラーを受信し、 |
アプリケーションは、新規接続を確立し(独自のLTXID-B 0を使用)、最後に失敗したセッションのLTXID (LTXID-A)を使用して |
新規LTXID-B 0 登録時にもJDBCコールバックを使用して設定します |
アプリケーションが、最後のセッション・トランザクション・ステータスが |
コミット済ステータスをクライアントに戻すと、アプリケーションを続行できます。 |
(該当なし) |
アプリケーションが、最後のセッション・トランザクション・ステータスが |
コミット済ステータスをクライアントに戻し、終了します。コール内の処理が完了していないため(たとえば、OUTバインドまたは行カウントが戻されなかった)、一部のアプリケーションは続行できません。アプリケーションが続行可能かどうかは、アプリケーションに依存します。 |
(該当なし) |
アプリケーションで、最後のセッション・トランザクション・ステータスが |
アプリケーションが結果をユーザーに返すか、必要であればクリーンアップし、有効な新セッションのLTXID (LTXID-B 0)を使用して再発行します。 新規リクエストによってコミットが実行されると、サーバーはLTXID-B 2以上のコミット・メッセージを戻します。 |
New LTXID-B 2 ..N 登録時にもJDBCコールバックを使用して設定します |
アプリケーションがリプレイを決定した場合、リカバリ可能なエラーを受信します。 |
アプリケーションは、新規接続を確立し(独自のLTXID-C 0を使用)、最後のセッションのLTXID (LTXID-B N)を使用して |
新規セッションのLTXID-C 0。 登録時にもJDBCコールバックを使用して設定します |
アプリケーションがリプレイを決定した場合、もう1つのリカバリ可能なエラーを受信します。 |
アプリケーションは、新規接続を確立し(独自のLTXID-D 0を使用)、最後のセッションのLTXID (LTXID-C N)を使用して |
新規セッションのLTXID-D 0。 登録時にもJDBCコールバックを使用して設定します |
接続プールは、LTXIDを管理するために別のユースケースを作成します。これは、接続およびセッションが事前に確立されて共有されるためです。接続プールおよび中間層の最も簡単なモデルでは、LTXIDはセッション・ハンドルごとに存在します。これは、接続プールからチェックアウトされる際にアプリケーション・リクエストに関連付けられ、プールにチェックインして戻される際にアプリケーション・リクエストから切断されます。チェックアウトとチェックインの間、セッションのLTXIDはこのアプリケーション・リクエストによって排他的に保持されます。チェックイン後、LTXIDはアイドル状態のプール・セッションに属します。これは、接続をチェックアウトする次のアプリケーション・リクエストに関連付けられます。
トランザクション・ガードをこの方法で使用する場合:
現在のHTTPリクエストに関する重複の検出およびフェイルオーバーをサポートできます
サード・パーティ・コンテナによる基本リプレイ(リカバリ不可能な停止後の最後のリクエストのリプレイ)をサポートできます
トランザクション・ガードは、開発者がリカバリ可能なエラー後に使用し、既知の結果を提供するためのツールです。これは、最後のセッションがデッド状態であることを示すエラーが戻されたときに使用する必要があります。
次の場合、トランザクション・ガードAPIは使用しないでください。
現在のセッションでGET_LTXID_OUTCOME
を使用しないでください。エラーが戻されます。
リカバリ可能なエラーを受信しなかったセッション(つまり、ライブ・セッション)でGET_LTXID_OUTCOME
を使用しないでください。このセッションのコミットはブロックされます。
別のユーザーから、または別のデータベースに対して、GET_LTXID_OUTCOME
を使用しないでください。エラーが戻されます。
即時使用するのではなく、後で使用する場合はLTXIDを取得および保存しないでください。GET_LTXID_OUTCOME
の結果が有効なのは、最後のオープン・トランザクションまたは完了したトランザクションに対してのみです。同じセッションで以前のトランザクションとともに使用すると、エラーが戻されます。
トランザクション・ガードには、データベース・トランザクションごとに一意の識別子(LTXID)が用意されています。この識別子は、トランザクションのコミット結果を問い合せるために使用したり、トランザクションが1回のみ適用されるようにするために使用できます。トランザクション・ガードはアプリケーション・コンティニュイティによって使用され、これによって自動的に有効化されますが、独立して有効化することもできます。トランザクション・ガードは、アプリケーション・コンティニュイティがリプレイするトランザクションが複数回適用されるのを阻止します。アプリケーションがアプリケーション・レベルのリプレイを実装した場合、冪等性を実現するためにアプリケーションをトランザクション・ガードと統合する必要があります。
パッケージ済リプレイの場合、アプリケーションはアプリケーション・コンティニュイティを使用できます。
参照:
|