トランザクション

このページのスクリプト・コンテンツはナビゲーションのみを目的としており、いかなる方法においても内容を変更するものではありません。

この章では、トランザクションを定義し、データベースでトランザクションが処理される方法について説明します。

トランザクションの概要

トランザクションとは、1つ以上のSQL文を含むアトミックな論理作業単位のことです。

トランザクションは、SQL文をグループ化して、すべての文がコミットされた(データベースに適用された)状態にするか、すべての文がロールバックされた(データベースから取り消された)状態にできる必要があります。Oracle AI Databaseでは、すべてのトランザクションにトランザクションIDと呼ばれる一意の識別子が割り当てられます。

すべてのOracleトランザクションは、データベース・トランザクション(ACIDプロパティ)の基本プロパティに従います。ACIDは次の単語の頭字語です。

トランザクションの使用は、データベース管理システムとファイル・システムの最も重要な違いの1つです。

サンプル・トランザクション: 口座の借方と貸方

トランザクションの概念を具体的に説明するため、銀行業務データベースについて考えてみます。

顧客が普通預金口座から当座預金口座へ預金を振り替える場合、トランザクションは次の3つの別々の操作で構成する必要があります。

Oracle AI Databaseでは、2つの状況が考慮される必要があります。3つのSQL文のすべてにおいて口座の差引残高の帳尻が合えば、トランザクションの結果をデータベースに適用できます。ただし、預金額の不足、口座番号が無効、またはハードウェア障害などの問題が原因で、トランザクション内の1つまたは2つの文が完了しない場合は、データベースではすべての口座の差引残高が正しく維持されるようにトランザクション全体をロールバックする必要があります。

次の図に、銀行取引を示します。最初の文では、普通預金口座3209から$500を減額します。2番目の文では、当座預金口座3208に$500を増額します。3番目の文では、ジャーナルの表にこの振替のレコードを挿入します。最後の文で、トランザクションをコミットします。

図1: 銀行のトランザクション

画像cncpt025.gifの説明

トランザクションの構造

データベース・トランザクションは、1つ以上の文で構成されています。

具体的には、トランザクションは次のいずれかで構成されています。

トランザクションには、開始と終了があります。

関連情報:

トランザクションの開始

トランザクションは、最初の実行可能SQL文が検出された時点で開始されます。

実行可能SQL文は、DML、DDL文、およびSET TRANSACTION文など、データベース・インスタンスへのコールを生成するSQL文です。

トランザクションが開始されると、Oracle AI Databaseはそのトランザクションを使用可能なUNDOデータ・セグメントに割り当てて、新しいトランザクションのUNDOエントリを記録します。トランザクションIDは、UNDOセグメントおよびトランザクション表スロットが割り当てられ、最初のDML文中に割り当てられるまで割り当てられません。トランザクションIDはトランザクションに対して一意であり、UNDOセグメント番号、スロットおよび順序番号を表します。

次の例では、UPDATE文を実行してトランザクションを開始し、このトランザクションの詳細をV$TRANSACTIONに問い合せます。

SQL> UPDATE hr.employees SET salary=salary;

107 rows updated.

SQL> SELECT XID AS "txn id", XIDUSN AS "undo seg", XIDSLOT AS "slot",
  2  XIDSQN AS "seq", STATUS AS "txn status"
  3  FROM V$TRANSACTION;

txn id             undo seg       slot        seq txn status
---------------- ---------- ---------- ---------- ----------------
0600060037000000          6          6         55 ACTIVE

関連項目: UNDOセグメント

トランザクションの終了

トランザクションは、様々な状況で終了する可能性があります。

トランザクションは、次のいずれかのアクションが発生すると終了します。

1つのトランザクションが終了すると、次の実行可能SQL文によって次のトランザクションが自動的に開始されます。次の例では、UPDATEを実行してトランザクションを開始し、ROLLBACK文でトランザクションを終了してから、UPDATEを実行して新しいトランザクションを開始します(トランザクションIDが異なることに注意してください)。

SQL> UPDATE hr.employees SET salary=salary;
107 rows updated.

SQL> SELECT XID, STATUS FROM V$TRANSACTION;

XID              STATUS
---------------- ----------------
0800090033000000 ACTIVE

SQL> ROLLBACK;

Rollback complete.

SQL> SELECT XID FROM V$TRANSACTION;

no rows selected

SQL> UPDATE hr.employees SET last_name=last_name;

107 rows updated.

SQL> SELECT XID, STATUS FROM V$TRANSACTION;

XID              STATUS
---------------- ----------------
0900050033000000 ACTIVE

関連情報:

文レベルの原子性

Oracle AI Databaseでは、文レベルの原子性がサポートされています。これは、SQL文がアトミック作業単位であり、完全に成功しているか、完全に失敗するかのいずれかであることを意味します。

正常に実行される文とコミットされるトランザクションとは異なります。1つのSQL文は、アトミックな単位として解析され、エラーなしで実行された場合、たとえば複数行の更新ですべての行が変更されたときなどに、正常に実行されます。

実行中にSQL文が原因でエラーが発生すると成功しないため、この文のすべての結果がロールバックされます。この操作が文レベルのロールバックです。この操作には次のような特徴があります。

文レベル・ロールバックの原因となるエラーの例には、重複する主キーの挿入が試行されます。1つのデッドロック(同じデータに関する競合)に単一SQL文が複数関係である場合も、文レベル・ロールバックが発生します。ただし、SQL文の解析中に構文エラーなどのエラーが検出された場合は、まだSQL文は実行されていないため、文レベルのロールバックは発生しません。

関連情報:

システム・チェンジ番号(SCN)

システム変更番号(SCN)とは、Oracle AI Databaseで使用される論理的な内部タイムスタンプのことです。

SCNを使用して、トランザクションのACIDプロパティに準拠する必要があるデータベース内で発生するイベントに順序を付けます。Oracle AI DatabaseではSCNを使用して、すべての変更がディスク上にあることが認識される前のSCNがマークされ、リカバリで不要なREDOの適用が適用されないようにします。さらに、データベースの集合に対するREDOが存在しない時点のマークにもSCNを使用し、リカバリを停止できるようにします。

SCNは直線的に増加する順序で発生します。監視されたSCNは時間における論理的な ある時点を示し、監視を繰り返すと等しい値と前よりも大きな値が戻されるため、Oracle AI DatabaseではSCNを本番時間のように使用できます。あるイベントのSCNが別のイベントのSCNよりも小さい場合、このイベントはそのデータベースで先に発生したことになります。複数のイベントが同じSCNを共有する場合も存在し、これは、イベントがデータベースで同時に発生したことを意味します。

すべてのトランザクションには、SCNがあります。たとえば、トランザクションで行が更新されると、データベースではこの更新が発生したときのSCNが記録されます。このトランザクションで行われたその他の変更にも同じSCNが付けられます。トランザクションがコミットされると、データベースではこのコミットのSCNが記録されます。

Oracle AI Databaseでは、SCNがシステム・グローバル領域(SGA)で増分されます。トランザクションでデータが変更されると、データベースではこのトランザクションに割り当てられたUNDOデータ・セグメントに新しいSCNが書き込まれる。次に、ログ・ライター・プロセスにより、このトランザクションのコミット・レコードがオンラインREDOログに即時に書き込まれますコミット・レコードには、トランザクションの一意のSCNが付けられています。Oracle AI Databaseでは、SCNをインスタンス・リカバリ・メカニズムおよびメディア・リカバリ・メカニズムの一部としても使用します。

参照: 「インスタンス・リカバリの概要」

トランザクション制御の概要

トランザクション制御: DML文による変更の管理と、トランザクションへのDML文のグループ化です。

通常、アプリケーション設計者は、作業が論理単位で完了してデータの一貫性が保たれるよう、トランザクション制御を考慮します。

トランザクション制御では、「トランザクション制御文」で説明したように、次の文が使用されます:

表13-1のセッションは、トランザクション制御の基本概念を示しています。

表1トランザクション制御

T セッション 説明
t0
COMMIT;
セッション内の既存のトランザクションを終了します。
t1
SET TRANSACTION NAME 'sal_update';
トランザクションを開始し、トランザクションにsal_updateという名前を付けます。
t2
UPDATE employees
 SET salary = 7000
  WHERE last_name = 'Banda';
Bandaの給与を7000に更新します。
t3
SAVEPOINT after_banda_sal;
after_banda_salという名前のセーブポイントを作成し、このトランザクションで行われた変更をこの時点までロールバックできるようにします。
t4
UPDATE employees
 SET salary = 12000
  WHERE last_name = 'Greene';
Greeneの給与を12000に更新します。
t5
SAVEPOINT after_greene_sal;
after_greene_salという名前のセーブポイントを作成し、このトランザクションで行われた変更をこの時点までロールバックできるようにします。
t6
ROLLBACK TO SAVEPOINT
 after_banda_sal;
この文により、トランザクションがt3にロールバックされ、t4で行われたGreeneの給与に対する更新が取り消されます。sal_updateトランザクションは終了しません。
t7
UPDATE employees
 SET salary = 11000
  WHERE last_name = 'Greene';
トランザクションsal_updateで、Greeneの給与を11000に更新します。
t8
ROLLBACK;
トランザクションsal_updateで行われたすべての変更をロールバックし、トランザクションを終了します。
t9
SET TRANSACTION NAME 'sal_update2';
セッションで新しいトランザクションを開始し、トランザクションにsal_update2という名前を付けます。
t10
UPDATE employees
 SET salary = 7050
  WHERE last_name = 'Banda';
Bandaの給与を7050に更新します。
t11
UPDATE employees
 SET salary = 10950
  WHERE last_name = 'Greene';
Greeneの給与を10950に更新します。
t12
COMMIT;
トランザクションsal_update2で行われたすべての変更をコミットし、トランザクションを終了します。このコミットにより、変更がオンラインREDOログ・ファイルに保存されることが保証されます。

取引名

トランザクション名は、ユーザー指定のオプションのタグであり、トランザクションが実行する作業のリマインダとして機能します。トランザクションの命名にはSET TRANSACTION ... NAME文を使用します。アクティブなトランザクションは、開始した後、まだトランザクションの最初の文として使用する必要があります。

表13-1では、最初のトランザクションがsal_update、2つ目のトランザクションがsal_update2と命名されています。

トランザクション名を使用すると、次のような利点があります。

関連情報:

アクティブなトランザクション

アクティブなトランザクションとは、開始した後、まだコミットまたはロールバックされていないトランザクションのものです。

表13-1では、sal_updateトランザクションでデータを変更する最初の文を、Bandaの給与の更新です。この更新の実行が成功するまで、ROLLBACK文がトランザクションを終了するまで、sal_updateトランザクションはアクティブです。

トランザクションによるデータ変更は、トランザクションがコミットまたはロールバックされるまでは一時的です。トランザクションが終了する前のデータの状態は、次の表のとおりです。

表2トランザクションが終了する前のデータの状態

状態 摘要 詳細を表示するには
Oracle AI Databaseにより、SGAにUNDO情報が生成されています。 このUNDOデータには、トランザクションのSQL文によって変更された古いデータ値が含まれています。 「コミット読取り分離レベルでの読取り一貫性」
Oracle AI Databaseにより、SGAのオンラインREDOログ・バッファにREDOが生成されています。 REDOログ・レコードには、データ・ブロックおよびUNDOブロックに対する変更内容が含まれています。 「REDOログ・バッファ」
SGAのデータベース・バッファに変更が加えられます。 コミットされたトランザクションのデータ変更は、SGAのデータベース・バッファに格納されており、データベース・ライター(DBW)によりデータファイルに必ずしもすぐに書き込まれるわけではありません。ディスクへの書込みは、コミットの前に行われることも、後に行われることもあります。 データベース・バッファ・キャッシュ
データ変更の影響を受ける行はロックされます。 他のユーザーは、影響を受ける行のデータを変更することも、未コミットの変更を表示することもできます。 「ロック動作の概要」

セーブポイント

セーブポイントは、トランザクションのコンテキスト内のユーザー宣言の中間マーカーです。

内部的には、セーブポイント・マーカーはSCNに解決されます。セーブポイントは、ロング・トランザクションをいくつかの小さい部分に分割します。

ロング・トランザクションでセーブポイントを使用すると、そのトランザクション内の宣言されたセーブポイントからトランザクション内の現時点までの間に実行された作業を、後でロールバックできるようになります。したがって、エラーが発生してもすべての文を再発行する必要はありません。表13-1では、Greeneの給与に対する更新をこのセーブ・ポイントまでロールバックできるように、セーブポイントafter_banda_salを作成します。

セーブポイントにロールバック

未コミットのトランザクションにおけるセーブポイントへのロールバックは、指定したセーブポイント後に行われたすべての変更の取消しを意味しますが、トランザクション自体のロールバックは意味しません。

表13-1でROLLBACK TO SAVEPOINT after_banda_salを実行したときのように、トランザクションがセーブポイントまでロールバックされると、次のことが行われます。

  1. Oracle AI Databaseは、セーブポイントの後に実行された文のみをロールバックします。

    表13-1では、ROLLBACK TO SAVEPOINTにより、Greeneに対するUPDATEがロールバックされますが、Bandaに対するUPDATEはロールバックされません。

  2. Oracle AI Databaseでは、ROLLBACK TO SAVEPOINT文に指定されたセーブポイントが保存されますが、それ以降のセーブポイントはすべて失われます。

    表13-1では、ROLLBACK TO SAVEPOINTによってafter_greene_salセーブポイントが失われます。

  3. Oracle AI Databaseにより、指定したセーブポイントの後に取得された表と行のすべてのロックが開放されますが、そのセーブポイントより後に取得されたすべてのデータ・ロックも保持されます。

トランザクションはアクティブであり、継続できます。

関連情報:

トランザクションのエンキュー

状況によっては、以前にロックされたリソースを待機しているトランザクションがセーブポイントへのロールバック後も引き続きブロックされる場合があります。

トランザクションが別のトランザクションによってブロックされた場合、このトランザクションはブロックしているトランザクション上でエンキューされるため、ブロックされたトランザクションを続行するには、ブロックしているトランザクション全体をコミットまたはロールバックする必要があります。

次の表に示すシナリオでは、セッション1でDML文が実行される前に作成されたセーブポイントに、セッション1がロールバックされます。ただし、セッション2はセッション1のトランザクションの完了を待機するため、引き続きブロックされます。

表3セーブポイントへのロールバックの例

T セッション 1 セッション 2 セッション 3 説明
t0
UPDATE employees
  SET salary=7000
  WHERE last_name=
  'Banda';
    セッション1でトランザクションが開始されます。このセッションでは、Bandaの行(TX)に排他ロック、表に副排他表ロック(SX)が適用されます。
t1
SAVEPOINT
  after_banda_sal;
    セッション1により、after_banda_salという名前のセーブポイントが作成されます。
t2
UPDATE employees
  SET salary=12000
  WHERE last_name=
  'Greene';
    セッション1により、Greeneの行がロックされます。
t3  
UPDATE employees
  SET salary=14000
  WHERE last_name=
 'Greene';
  セッション2により、Greeneの行の更新が試行されますが、セッション1でこの行がロックされているため、ロックを取得できません。セッション2ではトランザクションが開始しません。
t4
ROLLBACK
 TO SAVEPOINT
  after_banda_sal;
   

セッション1により、Greeneの給与の更新がロールバックされ、Greeneの行ロックが解放されます。t0で取得された表ロックは解放されません。

この時点で、セッション2は引き続きセッション1にブロックされています。これは、まだ完了していないセッション1のトランザクション上でセッション2がエンキューされているためです。

t5    
UPDATE employees
  SET salary=11000
 WHERE last_name=
 'Greene';
Greeneの行は現在ロックが解放されているため、セッション3により、Greeneの行を更新するためのロックが取得されています。この文により、セッション3のトランザクションが開始されます。
t6
COMMIT;
    セッション1がコミットし、そのトランザクションが終了します。セッション2は、セッション3のトランザクションの後でGreeneの行を更新するようにエンキューされました。

関連項目: Oracle AI Databaseによってロックは解放される時期についてさらに学習するには、「ロック期間」を参照してください

トランザクションのロールバック

未コミットのトランザクションをロールバックすると、そのトランザクション内のSQL文によって実行された、データに対するすべての変更が取り消されます。

トランザクションのロールバック後には、そのトランザクション内で実行された作業の結果は存在しません。セーブポイントを参照しないで、トランザクション全体をロールバックする場合、Oracle AI Databaseでは次の処理が実行されます。

ロールバックの持続時間は、変更されたデータ量の関数になります。

関連情報:

トランザクションのコミット

コミットは、現行のトランザクションを終了し、トランザクションで実行されたすべての変更を確定します。

表13-1では、2つ目のトランザクションがsal_update2で開始され、明示的なCOMMIT文で終了しています。これにより、2つのUPDATE文の結果である変更が確定されます。

トランザクションをコミットすると、次のアクションが実行されます。

トランザクションをコミットした後、ユーザーは変更を表示できます。

通常のコミットは、トランザクションのサイズにかかわらず高速な操作です。コミットの速度は、トランザクション内で変更されるデータのサイズによって遅くなりません。コミットで最も時間がかかる部分は、LGWRによって実行される物理ディスクI/Oです。ただし、LGWRではREDOログ・バッファの内容が段階的にバックグラウンドで書き込まれるため、LGWRにかかる時間は削減されます。

デフォルトの動作では、LGWRによりREDOがオンラインREDOログに同時に書き込まれ、トランザクションはバッファ内のREDOがディスクに移動するまで待機してから、コミットをユーザーに戻します。ただし、アプリケーション開発者は、トランザクションのコミット待機時間を短縮するために、REDOが非同期に書き込まれ、REDOがディスクに移動されるまでトランザクションが待機せずに、COMMITコールからすぐに戻れるよう指定できます。

関連情報:

隔離されたトランザクションの概要

隔離済トランザクションは、データベース・リカバリ中に分離されてリカバリされないトランザクションです。ロックを解放するには、問題を解決するためにDBAによる介入の必要があります。

Oracle AI Databaseでは、データの一貫性を確保するためにREDOおよびUNDOが使用されます。クラッシュの後でデータベースがオープンされると、REDOの適用によりデータベースがロールフォワードされ、コミットされたすべての変更(キャッシュ・リカバリと呼ばれる)が取得され、コミットされていない、クラッシュのために非アクティブになったトランザクションによって加えられた変更がUNDOによりロールバックされます。これはクラッシュ・リカバリと呼ばれます。データベースのオープンは、コミットされていないトランザクションのUNDOが適用されるのを待機せず、起動を高速化します。かわりに、トランザクション表においてそのトランザクションの状態が「非アクティブ」とマークされ、データベースがすぐにオープンされます。非アクティブなトランザクションに対するUNDO適用は、その後、システム・モニター(SMON)バックグラウンド・プロセスによって非同期に実行され、トランザクション・リカバリと呼ばれます。

非アクティブなトランザクションがSMONによってリカバリされているとき以外は、インスタンスのリカバリ中です。Oracle RACインスタンスは、アクティブに実行されているトランザクションでクラッシュする可能性があります。これらの非アクティブなトランザクションでは、他の残りのRACインスタンスで同じ行のトランザクションをブロックするローロックが保持されます。存続しているいずれかのインスタンスのSMONバックグラウンド・プロセスは、キャッシュ・リカバリーの2つのフェーズで、その後のトランザクション・リカバリで、インスタンス・リカバリを実行します。

また、PMONバックグラウンド・プロセスでは、失敗したプロセスをクリーン・アップする間に大規模なトランザクションを終了するという作業を、SMONにオフロードできます。

SMONプロセスでは、未使用の一時セグメントのクリーン・アップ、連続するエクステントの結合、その他の多くのタスクなどのシステム・レベルのタスクが実行されます。これはリカバリ不能なプロセスであり、SMONでクラッシュするとCDBインスタンスがクラッシュします。SMONトランザクションのリカバリの失敗は、次のような様々な理由で発生する可能性があります。

クラッシュが原因で、SMONによってアクティブにリカバリされているトランザクションのリカバリが停止するだけでなく、非アクティブ・トランザクションのリカバリも停止します。永続的な障害が発生した場合、Oracleサポートでは、SMONトランザクション・リカバリを無効にし、影響を軽減するためにデータベースをオープンすることをお薦めします。これにより、非アクティブなトランザクションによって行ロックが長期間保持されることになります。これは重要なビジネス操作に大きく影響します。

リカバリできないトランザクションはすべて隔離され、DBAが問題を解決するまでリカバリされないままになります。DBAは隔離されたトランザクションについて通知され、隔離されたトランザクションによって保持されている行ロックを解放できるように、即時にアクションを実行する必要があります。

DBAは、隔離されたトランザクションおよび隔離された理由の識別に役立てるために、様々なログおよびビューに隔離されたトランザクションがあることが通知されます。DBAは、隔離を削除できるように、この情報を使用して特定の問題に対処します。

コード不具合による論理データ破損、複数のブロックを物理的に破損、PDB SGAの破損など、複数のトランザクション間で障害が発生した場合や障害がPDB全体に渡っている場合、失敗した非アクティブなトランザクション・リカバリの隔離が役立つかどうかは不明です。他の非アクティブなトランザクションのリカバリで同じ問題が発生する可能性があるため、これらの障害の根本原因が同じかどうかによって異なります。いくつかのトランザクションを隔離した後でも、システムは一貫性のない状態で動作し続けます。障害が論理データ破損によるものである場合、時間の経過とともに分散するため、危険になる可能性があります。これを回避するために、3のトランザクションの隔離制限があります。その後、隔離がデータベース・レベルにエスカレートされ、PDBに対してアーカイブ・ロギングが有効になっていてPDBを停止できる場合は、shutdown abortを使用してPDBを終了します。PDBのトランザクション・リカバリは自動的に無効化されるため、DBAは次の起動時に問題を修正できます。問題が解決したら、DBAは次の起動時にリカバリを有効にする必要があります。

ノート: Oracle Data Guardは論理レプリケーションを使用するため、Oracle Data Guardの使用時に隔離メタデータはスタンバイ・サーバーにレプリケートされません。したがって、スタンバイ・サーバーのトランザクション隔離ビュー(DBA_QUARANTINED_TRANSACTIONSなど)のコンテンツは、プライマリ・サーバーのエントリとは異なる場合があります。

関連項目

トランザクション・ガードの概要

トランザクション・ガードは、アプリケーションがトランザクション冪等性およびを提供するために使用できるAPIの1つであり、これにより、データベースは、トランザクションがコミットされて完了しているかどうかを示す保証されたコミット結果を保持することができます。Oracle AI Databaseは、JDBCシン、OCI、OCCIおよびODP.Net用のAPIを提供します。

リカバリ可能エラーは、実行しているアプリケーション・セッション・ロジックとは無関係に、外部システムの障害が原因で起こります。リカバリ可能なエラーは、フォアグラウンド・プロセス、ネットワーク、ノード、記憶域およびデータベースの計画および計画外停止の後に発生します。停止によりクライアント・アプリケーションとデータベース間の接続が中断した場合、アプリケーションでは切断エラー・メッセージを受信します。接続の切断時に実行中だったトランザクションは、処理中のトランザクションと呼ばれます。

トランザクションを再送信するか、それとも結果(コミット済または未コミット)をクライアントに戻すかどうかを決めるため、アプリケーションでは処理中のトランザクションの結果を判断する必要があります。Oracle Database 12c以前は、クライアントに戻されたコミット・メッセージは残りませんでした。トランザクションをチェックしても、チェック後にそれがコミットされないと保証するものではなく、トランザクションの重複や他の形の論理的な破損が生じる可能性があります。たとえば、ユーザーがブックをオンラインで購入する際、Webブラウザをリフレッシュして、同じ本に対して2回請求される可能性があります。

関連情報:

トランザクション・ガードの利点

Oracle Database 12c以降では、トランザクション・ガードにより、リカバリ可能な停止の後、処理中のトランザクションのステータスを判断するためのツールが提供されています。

トランザクション・ガードを使用すれば、アプリケーションでは、トランザクションが1回しか実行されていないことを確認できます。たとえば、ネット書店アプリケーションで前に送信したコミットが失敗したことが確認されれば、アプリケーションは安全に再送信できます。

トランザクション・ガードでは、アプリケーションが重複送信が実行されないように、実行を1回のみにするためのツールを提供します。トランザクション・ガードでは、トランザクションごとに既知の結果を提供します。

トランザクション・ガードは、Oracle AI Databaseの中核機能である。アプリケーション・コンティニュイティでは、エンド・ユーザーに停止を隠すときにトランザクション・ガードを使用します。トランザクション・ガードがないと、エラー後に再試行するアプリケーションで、重複トランザクションがコミットされる可能性があります。

関連情報:

トランザクション・ガードの動作

この項では、失われたコミット・メッセージの問題と、トランザクション・ガードにより、論理トランザクションIDを使用してその問題がどのように解決されるかについて説明します。

失われたコミット・メッセージ

冪等性の設計時に、開発者は、コミット文送信後の通信エラーの問題に対処する必要があります。コミット・メッセージは、データベースに残らないため、エラー後に取得できません。

次の図は、クライアント・アプリケーションとデータベース間の対話をハイレベルに表現したものです。

図2: 失われたコミット・メッセージ

画像cncpt356.pngの説明

標準コミットの場合、データベースではトランザクションをコミットすると、クライアントに成功メッセージを戻します。図13-2では、クライアントがコミット文を送信し、通信が失敗したというメッセージを受信します。このタイプの失敗は、データベース・インスタンスの障害またはネットワークの停止など、いくつかの原因で発生する可能性があります。このシナリオでは、クライアントにはトランザクションの状態がわかりません。

通信の失敗後も、データベースではその送信を続行し、クライアントが切断されていることを認識していない場合があります。トランザクション状態をチェックしても、チェック後にアクティブ・トランザクションがコミットされないという保証にはなりません。この古い情報のために、クライアントがコミットを再送信した場合、データベースではトランザクションを繰り返し、論理的な破損が生じる可能性があります。

論理トランザクションID

Oracle AI Databaseでは、論理トランザクションIDというグローバルに一意の識別子を使用することで、通信障害を解決します、

このIDには、セッションの最初の接続時に割り当てられた論理セッション番号と、セッションのコミッションまたはロールバックごとに更新される実行コミット番号が含まれます。back.Foot 1アプリケーション側からとすると、論理トランザクションIDは、失敗したセッションで送信された最後のデータベース・トランザクションを一意に識別します。

データベースでは、1つ以上のトランザクションがコミットされるクライアントからのラウンド・トリップごとに1つの論理トランザクションIDが格納されます。このIDにより、データをコミットするラウンド・トリップごとに、アプリケーションとデータベース間の対話のために、トランザクション冪等度を提供できます。

1回限りのプロトコルにより、データベースに次のことを要求することで、コミット結果へのアクセスが可能になります。

トランザクションの実行中、データベースとクライアントの両方で、論理トランザクションIDが保持されます。データベースでは、認証時には接続プールから、各ラウンド・トリップでは1つ以上のコミット操作を実行するクライアント・ドライバから借りて、論理トランザクションIDをクライアントに与えます。

リカバリ可能なエラーの後、最後のトランザクションの結果が確認できるように、アプリケーションでは、Java、OCI、OCCIまたはODP.Net APIを使用して、クライアントで保持されている論理トランザクションIDを取得します。次に、アプリケーションではPL/SQLプロシージャDBMS_APP_CONT.GET_LTXID_OUTCOMEを論理トランザクションIDで起動して、最後の送信結果のコミット済(trueまたはfalse)およびユーザー・コール完了(trueまたはfalse)を確認します。

トランザクション・ガードを使用すると、アプリケーションでは、エラーがリカバリ可能で、セッションでの最後のトランザクションがコミットされていない場合、トランザクションを再生できます。最後のトランザクションがコミットされていて、ユーザー・コールが完了している場合、アプリケーションは続行可能です。アプリケーションでは、クライアントが次にとるべきアクションを決定できるように、トランザクション・ガードを使用して既知の結果をクライアントに戻すことができます。

関連情報:

トランザクション・ガード: 例

このシナリオでは、リカバリ可能エラーのためにコミット・メッセージが失われています。

トランザクション・ガードでは、論理トランザクションIDを使用して、COMMIT文の結果を保存し、トランザクションに既知の結果があることを保証します。

図3: 論理トランザクションのステータスのチェック

画像cncpt365.pngの説明

図13-3では、データベースがアプリケーションに、トランザクションがコミットされたかどうか、および最後のユーザー・コールが完了したかどうかを知らせます。その結果、アプリケーションではエンド・ユーザーに結果を戻すことができます。可能性は次のとおりです。

関連項目:トランザクション・ガードの使用方法を学習するには、『Oracle AI Database開発ガイド』

アプリケーション・コンティニュイティの概要

アプリケーション・コンティニュイティでは、計画済および計画外の停止後に完了していないアプリケーション・リクエストをリプレイすることで、停止をアプリケーションからマスキングしようとします。このような状況では、リクエストがアプリケーションからの作業単位です。

通常、リクエストは、1つのデータベース接続におけるDML文や、1つのWebリクエストに対するその他のデータベース・コールに対応しています。一般に、リクエストは、データベース接続のチェックアウトとチェックインの間で、接続プールから行われるコールにより区別されます。

この項では、次のトピックについて説明します:

アプリケーション・コンティニュイティの利点

開発者にとっての基本的な問題は、失われたデータベース・セッションをエンド・ユーザーから隠す方法です。

アプリケーション・コンティニュイティでは、コンポーネントによりデータベースとクライアント間の対話が中断した場合、データベース・セッションをリストアすることで、失われたセッションの問題を解決しようとします。リストアされたデータベース・セッションには、すべての状態、カーソル、変数、およびトランザクションが存在する場合は最新のトランザクションが含まれます。

アプリケーション・コンティニュイティのユースケース

典型的な例では、クライアントがデータベースにリクエストを送信すると、トランザクション状態と非トランザクション状態の両方が構築されます。

クライアントでの状態は現行のままですが、入力されたデータ、戻されたデータ、キャッシュされたデータや変数がある可能性があります。ただし、アプリケーションが動作するために必要とするデータベース・セッションの状態は失われます。

クライアント・リクエストにより1つ以上のトランザクションが開始される場合、アプリケーションでは次の可能性に直面します。

リプレイが成功した場合、計画および計画外停止のためのデータベース・ユーザー・サービスは中断されません。アプリケーションで表示され、場合によっては実行されているデータ変更をデータベースが検出した場合、リプレイは拒否されます。リプレイ開始の許容時間を超過している場合、アプリケーションで制限されたコールを使用する場合、またはアプリケーションでdisableReplayメソッドを使用してリプレイを明示的に無効にしている場合、リプレイは試行されません。

関連項目:データベース・セッションでのアプリケーション・コンティニュイティの動作についてさらに学習するには、『Oracle Real Application Clusters管理およびデプロイメント・ガイド』を参照してください。

計画的メンテナンスに対するアプリケーション・コンティニュイティ

計画済停止に対するアプリケーション・コンティニュイティにより、アプリケーションは確実に排出または移行できるデータベース・セッションの操作を続行できます。

スケジュール済メンテナンスではアプリケーション作業を中断する必要はありません。アプリケーション・コンティニュイティにより、現在の位置からメンテナンスの影響を現在受けていない新しい位置まで排出するためのアクティブな作業時間が提供されます。排出間隔の終了時に、メンテナンスが計画されたデータベース・インスタンス上にセッションが残る可能性があります。アプリケーション・コンティニュイティでは、これらのセッションを強制的に切断するかわりに、残りのサイトにこれらのセッションをフェイルオーバーし、処理中のトランザクションを再送信できます。

アプリケーション・コンティニュイティを有効にすると、データベースで次のことを実現できます。

SRVCTLユーティリティ、Global Data Services制御ユーティリティ(GDSCTL)およびOracle Data Guard Brokerのdrain_timeoutおよびstop_optionサービス属性を使用して、計画的メンテナンス中の排出動作を制御します。DBMS_SERVICEパッケージは、基礎となるインフラストラクチャを提供します。

関連情報:

アプリケーション・コンティニュイティ・アーキテクチャ

アプリケーション・コンティニュイティの主なコンポーネントは、実行時、再接続およびリプレイです。

フェーズは次のとおりです。

  1. 通常の実行時

    このフェーズでは、アプリケーション・コンティニュイティによって次のタスクが実行されます。

    • データベース・リクエストを識別する

    • ローカル・コールとデータベース・コールがリプレイ可能かどうかを判定する

    • リプレイの有効化と(必要に応じて)キューの管理を行うためのプロキシ・オブジェクトを作成する

    • データベース・リクエストが終了するか、リプレイが無効になるまで、元コールとこれらのコールの検証を保持します

  2. 再コネクション

    このフェーズは、リカバリ可能なエラーによってトリガーされます。アプリケーション・コンティニュイティによって次のタスクが実行されます。

    • データベース・リクエストのリプレイが有効であることを確認する

    • タイムアウトを管理する

    • データベースへの新しい接続を取得し、それが有効なデータベース・ターゲットであることを検証する

    • トランザクション・ガードを使用して、最後のトランザクションが正常にコミットされたかどうかを判定する(コミットされたトランザクションは再送信されない)

  3. リプレイ

    アプリケーション・コンティニュイティによって次のタスクが実行されます。

    • キューに保持されているコールをリプレイする

    • ユーザーが参照可能な結果の変更がリプレイ中に出現した場合は、リプレイを無効にする

    • コミットは許可しないが、(エラーが発生した)最後のリコールのコミットは許可する

リプレイに成功した後は、障害点からリクエストが続行されます。

関連情報:

自律型トランザクションの概要

自律型トランザクションとは、メイン・トランザクションである別のトランザクションからコールできる独立したトランザクションです。コール側のトランザクションを一時停止して、自律型トランザクション内でSQL操作を実行し、その操作をコミットまたは取り消してから、コール側トランザクションを再開できます。

自律型トランザクションは、コール側トランザクションでコミットまたはロールバックするかどうかに関係なく、独立して実行する必要があるアクションを実装する場合に便利です。たとえば、株式購入のトランザクションでは、全体的な株購入の成立かどうかにかかわらず、顧客データをコミットします。また、トランザクション全体がロールバックされた場合でも、デバッグ表にエラー・メッセージを記録することも必要となります。

自律型トランザクションの特性は、次のとおりです。

PL/SQLでは、自律型トランザクションは自律型スコープ内で実行されます(自律型コードスコープとは、プラグマAUTONOMOUS_TRANSACTIONでマークされたルーチンです)。このコンテキストでは、トップレベルの無名PL/SQLブロックおよびPL/SQLサブプログラムとPL/SQLトリガーが、ルーチンに含まれています。プラグマは、コンパイラにコンパイル・オプションの実行を指示するディレクティブです。プラグマAUTONOMOUS_TRANSACTIONによって、このプロシージャは実行時に親トランザクションから独立した新しい自律型トランザクションとして実行する必要があることが、データベースに指示されます。

次の図に、制御がメイン・ルーチン(MT)から自律型ルーチンに移り、再びメイン・ルーチンに戻ってくるまでのフローを示します。メイン・ルーチンはproc1、自律型ルーチンはproc2です。自律型ルーチンでは、制御がメイン・ルーチンに戻る前に、複数のトランザクション(AT1およびAT2)をコミットできます。

図4: トランザクション制御フロー

画像cncpt288.gifの説明

自律型ルーチンの実行可能セクションに入ると、メイン・ルーチンが一時停止します。この自律型ルーチンを終了すると、メイン・ルーチンが再開されます。

図13-4では、proc1内部のCOMMITにより、この文自体の作業のみでなく、そのセッション内で実行されたすべての保留中の作業が確定されます。ただし、proc2内のCOMMITでは、proc2トランザクション内で実行された作業のみが確定されます。したがって、トランザクションAT1およびAT2内のCOMMIT文は、MTトランザクションに影響を与えません。

関連項目:自律型トランザクションの使用方法を学習するには、Oracle AI Database開発ガイドおよびOracle AI Database PL/SQL言語リファレンスを参照してください。

分散トランザクションの概要

分散トランザクションとは、データベース・リンクと呼ばれるスキーマ・オブジェクトを使用し、分散データベースの複数の異なるノード上でデータを更新する、1つ以上の文を含むトランザクションです。

分散データベースは、分散システム内のデータベースの集合であり、アプリケーションには1つのデータソースとして認識できます。データベース・リンクは、1つのデータベース・インスタンスが別のデータベース・インスタンスにログインする方法を記述します。

ローカル・データベースでのトランザクションとは異なり、分散トランザクションでは、複数データベース上にあるデータが変更されます。その結果、データベースではトランザクションでの変更のコミットやロールバックをアトミックな単位として処理する必要があるため、分散トランザクション処理はより複雑になります。トランザクション全体をコミットまたはロールバックする必要があります。Oracle AI Databaseは、ネットワーク全体でトランザクション制御を調整し、ネットワーク障害が発生した場合にもデータ整合性が保たれる必要があります。

2フェーズ・コミット

2フェーズ・コミット・メカニズムは、分散トランザクションに関係するすべてのデータベースが、そのトランザクション内の文の全てをコミットするか、すべてを取り消すかのどちらか一方だけになるように保証するツールです。このメカニズムでは、整合性制約、リモート・プロシージャ・コールおよびトリガーによって実行される暗黙的DMLも保護されます。

複数データベース間の2フェーズ・コミットでは、1つのデータベースで分散トランザクションが調整されます。開始ノードはグローバル・コーディネータと呼ばれます。このコーディネータによって、他のデータベースでコミットの準備ができているかどうかが確認されます。いずれかのデータベースで否定のレスポンスがあった場合は、トランザクション全体がロールバックされます。すべてのデータベースから肯定のレスポンスがあった場合は、コーディネータによってメッセージがブロードキャストされ、各データベースでコミットが確定されます。

2フェーズ・コミット・メカニズムは、分散トランザクションを発行するユーザーからは意識されません。事実、ユーザーは、トランザクションが分散していることも認識する必要はありません。トランザクションの終了を示すCOMMIT文は、自動的に2フェーズ・コミット・メカニズムをトリガーします。データベース・アプリケーション本体に分散トランザクションを含めるのに、コーディングや複雑な構文の記述は必要ありません。

関連情報:

インダウト・トランザクション

インダウト分散トランザクションは、システム障害が発生したか、ネットワーク障害によって2フェーズ・コミットが中断されたときに発生します。

たとえば、2つのデータベースから調整データベースにコミットの準備ができたことが報告されたものの、このメッセージの受信直後に調整データベース・インスタンスが失敗した場合などです。この場合、コミットの準備ができている2つのデータベースはハング状態となり、結果の通知を待機し続けます。

リカバラ(RECO)・バックグラウンド・プロセスでは、インダウト分散トランザクションの結果が自動的に解決されます。障害が修復され、通信が再確立された後、各ローカルのOracleデータベースのRECOプロセスが、関係するすべてのノード上でインダウト分散トランザクションを自動的にコミットするか、ロールバックします。

長時間にわたる障害が発生した場合、Oracle AI Databaseでは、各ローカル管理者が障害によって引き起こされたインダウト分散トランザクションを手動でコミットまたは取り消すことができます。このオプションにより、ローカル・データベース管理者は、長時間にわたる障害によって無期限にロックされる可能性のあるリソースを解放することができます。

あるデータベースを過去のある時点までリカバリする必要がある場合、データベースのリカバリ機能を使用すると、他のサイトのデータベース管理者が、自分のデータベースを以前の同じ時点に戻すことができます。この操作により、グローバル・データベースは一貫した状態に保たれます。

関連情報:


脚注の説明

脚注1:

Oracle Real Application Clusters (Oracle RAC)の場合、論理トランザクションIDには、接頭辞としてデータベース・インスタンス番号が含まれます。