この章では、トランザクションを定義し、データベースでトランザクションが処理される方法について説明します。
この章の内容は、次のとおりです。
トランザクションは、1つ以上のSQL文を含むアトミックな論理作業単位です。トランザクションは、SQL文をグループ化して、すべての文がコミットされた(データベースに適用された)状態にするか、すべての文がロールバックされた(データベースから取り消された)状態にできる必要があります。Oracle Databaseでは、すべてのトランザクションにトランザクションIDと呼ばれる一意の識別子が割り当てられます。
すべてのOracleトランザクションは、ACIDプロパティと呼ばれる、データベース・トランザクションの基本プロパティに準拠します。ACIDは次の単語の頭字語です。
Atomicity(原子性)
1つのトランザクションでは、すべてのタスクが実行されるか、1つも実行されないかのいずれかです。部分的に実行されるトランザクションは存在しません。たとえば、トランザクションで100行の更新が開始され、20行が更新された後にシステムで障害が発生した場合、データベースではこの20行に行われた変更がロールバックされます。
一貫性
トランザクションにより、データベースは一貫したある状態から一貫した別の状態に移行します。たとえば、普通預金口座の借方に記入し、当座預金口座の貸方に記入する銀行のトランザクションにおいて、障害によって、データベースで一方の口座でのみ貸方に記入されたためにデータの一貫性がなくなることは許されません。
Isolation(独立性)
トランザクションの結果は、そのトランザクションがコミットされるまで、他のトランザクションに表示されません。たとえば、hr.employees
表を更新しているユーザーには、別のユーザーがemployees
に対して同時に行った未コミットの変更は表示されません。このため、ユーザーには、トランザクションがシリアルに実行されているように見えます。
Durability(永続性)
コミットされたトランザクションによって行われた変更は、永続的に確定されます。トランザクションの完了後、データベースではリカバリ・メカニズムを使用して、トランザクションによる変更が失われていないことが確認されます。
トランザクションの使用は、データベース管理システムとファイルシステムの最も重要な違いの1つです。
トランザクションの概念を具体的に説明するため、銀行業務データベースについて考えてみます。顧客が普通預金口座から当座預金口座へ預金を振り替える場合、トランザクションは次の3つの別々の操作で構成する必要があります。
普通預金口座の減額
当座預金口座の増額
トランザクション・ジャーナルへのトランザクションの記録
Oracle Databaseでは、2つの状況が考慮されます。3つのSQL文のすべてにおいて口座の差引残高の帳尻が合えば、トランザクションの結果をデータベースに適用できます。ただし、預金額の不足、口座番号が無効、またはハードウェア障害などの問題が原因で、トランザクション内の1つまたは2つの文が完了しない場合は、データベースではすべての口座の差引残高が正しく維持されるようにトランザクション全体をロールバックする必要があります。
図10-1に、銀行のトランザクションを示します。最初の文では、普通預金口座3209から$500を減額します。2番目の文では、当座預金口座3208に$500を増額します。3番目の文では、ジャーナルの表にこの振替のレコードを挿入します。最後の文で、トランザクションをコミットします。
データベース・トランザクションは、1つ以上の文で構成されています。具体的には、トランザクションは次のいずれかで構成されています。
全体でデータベースに対するアトミックな変更を構成する1つ以上のデータ操作言語(DML)文
1つのデータ定義言語(DDL)文
トランザクションには、開始と終了があります。
トランザクションは、最初の実行可能SQL文が検出された時点で開始されます。実行可能SQL文は、DML文やDDL文、およびSET TRANSACTION文など、データベース・インスタンスへのコールを生成するSQL文のことです。
トランザクションが開始されると、Oracle 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
トランザクションは、次のいずれかのアクションが発生すると終了します。
COMMIT
文またはROLLBACK
文が、SAVEPOINT句なしで
発行される場合。
コミットでは、ユーザーが明示的または暗黙的に、このトランザクションの変更内容を確定するように要求します。トランザクションによって行われた変更内容が確定され、トランザクションのコミット後にのみ他のユーザーが参照できるようになります。図10-1に示したトランザクションは、コミットで終了しています。
CREATE
、DROP
、RENAME
またはALTER
などのDDLコマンドが実行される場合。
データベースでは、すべてのDDL文の前後に暗黙的なCOMMIT
文が発行されます。現行のトランザクションにDML文が含まれている場合、Oracle Databaseは最初にそのトランザクションをコミットし、新しい単一文トランザクションとしてそのDDL文を実行し、コミットします。
ユーザーがほとんどのOracle Databaseユーティリティおよびツールを正常に終了する場合(このような場合は、現行のトランザクションが暗黙的にコミットされます)。ユーザーが切断したときのコミット動作は、アプリケーションに依存しており、構成可能です。
クライアント・プロセスが異常終了し、トランザクション表および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 Databaseでは、文レベルの原子性がサポートされます。文レベルの原子性とは、SQL文がアトミックな作業単位であり、完全に成功するか、完全に失敗するかのいずれかであることを意味します。
正常に実行される文とコミットされるトランザクションとは異なります。1つのSQL文は、アトミックな単位として解析され、エラーなしで実行された場合、たとえば複数行の更新ですべての行が変更されたときなどに、正常に実行されます。
実行中にSQL文が原因でエラーが発生すると成功しないため、この文のすべての結果がロールバックされます。この操作が文レベルのロールバックです。この操作には次のような特徴があります。
SQL文が成功しなかった場合は、SQLでの実行予定の作業のみが影響を受けます。
成功しなかった文が、現行のトランザクションにおけるこれまでの作業に影響を及ぼすことはありません。たとえば、図10-1
で、2番目のUPDATE文でエラーが発生してロールバックされた場合、最初のUPDATE
文によって実行された作業はロールバックされません。最初のUPDATE
文は、ユーザーが明示的にコミットまたはロールバックできます。
ロールバックの効果は、その文がまったく実行されなかった場合と同じ状態にすることです。
アトミックな文の副次的な効果としては、たとえば、文の実行時に起動されたトリガーが、アトミックな文の一部とみなされることがあげられます。アトミックな文の一部として生成された作業は、すべてが成功するか、1つも成功しないかのいずれかです。
文レベル・ロールバックの原因となるエラーの例として、重複する主キーの挿入を試行する場合があります。1つのデッドロック(同じデータに関する競合)に単一SQL文が複数関係している場合も、文レベル・ロールバックが発生します。ただし、SQL文の解析中に構文エラーなどのエラーが検出された場合は、まだSQL文は実行されていないため、文レベルのロールバックは発生しません。
システム変更番号(SCN)は、Oracle Databaseで使用される論理的な内部タイムスタンプです。SCNを使用して、トランザクションのACIDプロパティに準拠する必要があるデータベース内で発生するイベントに順序を付けます。Oracle DatabaseではSCNを使用して、すべての変更がディスク上に存在することが認識される前のSCNをマークし、リカバリで不要なREDOが適用されないようにします。さらに、データの集合に対するREDOが存在しない時点のマークにもSCNを使用し、リカバリを停止できるようにします。
SCNは直線的に増加する順序で発生します。監視されたSCNは時間における論理的なある時点を示し、監視を繰り返すと等しい値または前よりも大きな値が戻されるため、Oracle DatabaseではSCNを実時間のように使用できます。あるイベントのSCNが別のイベントのSCNよりも小さい場合、このイベントはそのデータベースに関して先行する時間に発生したことになります。複数のイベントが同じSCNを共有する場合もあり、これはイベントがデータベースに関して同じ時間に発生したことを意味します。
すべてのトランザクションには、SCNがあります。たとえば、トランザクションで行が更新されると、データベースではこの更新が発生したときのSCNが記録されます。このトランザクションで行われたその他の変更にも同じSCNが付けられます。トランザクションがコミットされると、データベースではこのコミットのSCNが記録されます。
Oracle Databaseでは、SCNがシステム・グローバル領域(SGA)で増分されます。トランザクションでデータが変更されると、データベースではこのトランザクションに割り当てられたUNDOデータ・セグメントに新しいSCNが書き込まれます。次に、ログ・ライター・プロセスによって、このトランザクションのコミット・レコードがオンラインREDOログに即時に書き込まれます。コミット・レコードには、トランザクションの一意のSCNが付けられています。Oracle Databaseでは、SCNをインスタンス・リカバリ・メカニズムおよびメディア・リカバリ・メカニズムの一部としても使用します。
トランザクション制御は、DML文による変更の内容を管理し、一覧のDML文をトランザクションとしてグループ化する処理です。通常、アプリケーション設計者は、作業が論理単位で完了してデータの一貫性が保たれるよう、トランザクション制御を考慮します。
トランザクション制御では、「トランザクション制御文」で説明したように、次の文が使用されます。
COMMIT
文は、現行のトランザクションを終了し、トランザクションで実行されたすべての変更を確定します。さらに、COMMIT
文により、トランザクション内のすべてのセーブポイントが消去され、トランザクション・ロックが解放されます。
ROLLBACK
文は、現行のトランザクションで行われた作業を元に戻し、最後のCOMMIT
またはROLLBACK
以降に行われたすべてのデータ変更が破棄されます。ROLLBACK TO SAVEPOINT
文は、最後のセーブポイント以降の変更を取り消しますが、トランザクション全体は終了しません。
表10-1のセッションは、トランザクション制御の基本概念を示しています。
表10-1 トランザクション制御
時間 | セッション | 説明 |
---|---|---|
t0 |
COMMIT; |
セッション内の既存のトランザクションを終了します。 |
t1 |
SET TRANSACTION NAME 'sal_update'; |
トランザクションを開始し、トランザクションに |
t2 |
UPDATE employees SET salary = 7000 WHERE last_name = 'Banda'; |
Bandaの給与を7000に更新します。 |
t3 |
SAVEPOINT after_banda_sal; |
|
t4 |
UPDATE employees SET salary = 12000 WHERE last_name = 'Greene'; |
Greeneの給与を12000に更新します。 |
t5 |
SAVEPOINT after_greene_sal; |
|
t6 |
ROLLBACK TO SAVEPOINT after_banda_sal; |
トランザクションをt3までロールバックし、t4で行われたGreeneの給与の更新を取り消します。 |
t7 |
UPDATE employees SET salary = 11000 WHERE last_name = 'Greene'; |
トランザクション |
t8 |
ROLLBACK; |
トランザクション |
t9 |
SET TRANSACTION NAME '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; |
トランザクション |
関連項目: トランザクション制御文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。 |
トランザクション名は、ユーザー指定のオプションのタグであり、トランザクションが実行する作業のリマインダとして機能します。トランザクションの命名にはSET TRANSACTION
...
NAME
文を使用し、トランザクションの最初の文として使用する必要があります。表10-1では、最初のトランザクションがsal_update
、2つ目のトランザクションがsal_update2
と命名されています。
トランザクション名を使用すると、次のような利点があります。
名前を付けることで、長時間実行中のトランザクションの監視およびインダウト分散トランザクションの解決が容易になります。
アプリケーションのトランザクションIDとともにトランザクション名を表示できます。たとえば、システムの活動状況を監視する場合、データベース管理者はOracle Enterprise Manager(Enterprise Manager)内のトランザクション名を表示できます。
トランザクション名はトランザクション監査REDOレコードに書き込まれるため、LogMinerを使用してREDOログ内の特定のトランザクションを検索できます。
トランザクション名を使用して、V$TRANSACTION
などのデータ・ディクショナリ・ビュー内の特定のトランザクションを検索できます。
関連項目:
|
アクティブなトランザクションとは、開始した後、まだコミットまたはロールバックされていないトランザクションのことです。表10-1では、sal_update
トランザクションでデータを変更する最初の文が、Bandaの給与の更新です。この更新の実行が成功してからROLLBACK
文がトランザクションを終了するまで、sal_update
トランザクションはアクティブです。
トランザクションによるデータ変更は、トランザクションがコミットまたはロールバックされるまでは一時的です。トランザクションが終了する前のデータの状態は、次のとおりです。
Oracle Databaseにより、システム・グローバル領域(SGA)内にUNDOデータ情報が生成されます。
このUNDOデータには、トランザクションのSQL文によって変更された古いデータ値が含まれています。「コミット読取り分離レベルでの読取り一貫性」を参照してください。
Oracle Databaseにより、SGAのオンラインREDOログ・バッファにREDOが生成されています。
REDOログ・レコードには、データ・ブロックおよびUNDOブロックに対する変更内容が含まれています。「REDOログ・バッファ」を参照してください。
SGAのデータベース・バッファに変更が加えられます。
コミットされたトランザクションのデータ変更は、SGAのデータベース・バッファに格納されており、データベース・ライター(DBW)によりデータファイルに必ずしもすぐに書き込まれるわけではありません。ディスクへの書込みは、コミットの前に行われることも、後に行われることもあります。「データベース・バッファ・キャッシュ」を参照してください。
データ変更の影響を受ける行はロックされます。
他のユーザーは、影響を受ける行のデータを変更することも、未コミットの変更を表示することもできません。「ロック動作の概要」を参照してください。
セーブポイントは、トランザクションのコンテキスト内のユーザー宣言による中間マーカーです。内部的には、このマーカーはSCNに解決されます。セーブポイントは、ロング・トランザクションをいくつかの小さい部分に分割します。
ロング・トランザクションでセーブポイントを使用すると、そのトランザクション内の宣言されたセーブポイントからトランザクション内の現時点までの間に実行された作業を、後でロールバックできるようになります。したがって、エラーが発生してもすべての文を再発行する必要はありません。表10-1では、セーブポイントafter_banda_sal
を作成しているため、Greeneの給与に対する更新をこのセーブポイントまでロールバックできます。
未コミットのトランザクションにおけるセーブポイントへのロールバックは、指定したセーブポイント後に行われたすべての変更の取消しを意味しますが、トランザクション自体のロールバックは意味しません。表10-1
でROLLBACK TO SAVEPOINT after_banda_salを実行したときのように、トランザクションがセーブポイントまでロールバックされると、次の処理が行われます。
Oracle Databaseにより、セーブポイントの後に実行された文のみがロールバックされます。
表10-1では、ROLLBACK TO SAVEPOINT
により、Greeneに対するUPDATE
がロールバックされますが、Bandaに対するUPDATE
はロールバックされません。
Oracle Databaseでは、ROLLBACK TO SAVEPOINT
文に指定されたセーブポイントは保存されますが、それより後のセーブポイントはすべて失われます。
表10-1では、ROLLBACK TO SAVEPOINT
によってafter_greene_sal
セーブポイントが失われます。
Oracle Databaseにより、指定したセーブポイントの後に取得された表と行のすべてのロックが解放されますが、そのセーブポイントより前に取得されたすべてのデータ・ロックは保持されます。
トランザクションはアクティブであり、継続できます。
関連項目:
|
状況によっては、以前にロックされたリソースを待機中のトランザクションが、セーブポイントへのロールバック後も引き続きブロックされる場合があります。トランザクションが別のトランザクションによってブロックされた場合、このトランザクションはブロックしているトランザクション上でエンキューされるため、ブロックされたトランザクションを続行するには、ブロックしているトランザクション全体をコミットまたはロールバックする必要があります。
表10-2に示すシナリオでは、セッション1でDML文が実行される前に作成されたセーブポイントに、セッション1がロールバックされます。ただし、セッション2はセッション1のトランザクションの完了を待機するため、引き続きブロックされます。
表10-2 セーブポイントへのロールバックの例
時間 | セッション1 | セッション2 | セッション3 | 説明 |
---|---|---|---|---|
t0 |
UPDATE employees SET salary = 7000 WHERE last_name = 'Banda'; |
|
|
セッション1でトランザクションが開始されます。このセッションでは、 |
t1 |
SAVEPOINT after_banda_sal; |
セッション1により、 |
||
t2 |
UPDATE employees SET salary = 12000 WHERE last_name = 'Greene'; |
|
|
セッション1により、 |
t3 |
|
UPDATE employees SET salary = 14000 WHERE last_name = 'Greene'; |
|
セッション2により、 |
t4 |
ROLLBACK TO SAVEPOINT after_banda_sal; |
|
|
セッション1により、 この時点で、セッション2は引き続きセッション1にブロックされています。これは、まだ完了していないセッション1のトランザクション上でセッション2がエンキューされているためです。 |
t5 |
|
|
UPDATE employees SET salary = 11000 WHERE last_name = 'Greene'; |
|
t6 |
COMMIT; |
|
|
セッション1がコミットし、そのトランザクションが終了します。セッション2は現在、セッション3のトランザクションの後で |
未コミットのトランザクションをロールバックすると、そのトランザクション内のSQL文によって実行された、データに対するすべての変更が取り消されます。トランザクションのロールバック後には、そのトランザクション内で実行された作業の結果は存在しません。
セーブポイントを参照しないで、トランザクション全体をロールバックした場合、Oracle Databaseでは次の処理が実行されます。
トランザクションのすべてのSQL文によるすべての変更が、対応するUNDOセグメントを使用して取り消されます。
すべてのアクティブなトランザクションのトランザクション表エントリには、そのトランザクションのすべてのUNDOデータを示すポインタが(適用時とは逆の順序で)格納されています。データベースでは、UNDOセグメントからデータを読み取り、操作を逆順にして、適用されたとおりにUNDOエントリをマークします。したがって、トランザクションで行が挿入されると、ロールバックによって削除されます。トランザクションで行が更新されると、ロールバックによって更新が元に戻されます。トランザクションで行が削除されると、ロールバックによって再挿入されます。表10-1では、GreeneとBandaの給与の更新が、ROLLBACK
によって元に戻されています。
トランザクションで保持されているすべてのデータ・ロックが解放されます。
トランザクション内のすべてのセーブポイントが消去されます。
表10-1では、ROLLBACK
によってセーブポイントafter_banda_sal
が削除されています。セーブポイントafter_greene_sal
は、ROLLBACK TO SAVEPOINT
文によって削除されています。
トランザクションを終了します。
表10-1では、ROLLBACK
によって、データベースは最初のCOMMIT
が実行された後と同じ状態で残ります。
ロールバックの持続時間は、変更されたデータ量の関数になります。
コミットは、現行のトランザクションを終了し、トランザクションで実行されたすべての変更を確定します。表10-1では、2つ目のトランザクションがsal_update2
で開始され、明示的なCOMMIT
文で終了しています。これにより、2つのUPDATE
文の結果である変更が確定されます。
トランザクションをコミットすると、次のアクションが実行されます。
COMMITに対してシステム変更番号(SCN)が生成されます。
関連するUNDO表領域の内部トランザクション表に、トランザクションのコミットが記録されます。トランザクションに対応する一意のSCNは、トランザクション表に割り当てられて記録されます。「シリアライズ可能分離レベル」を参照してください。
ログ・ライター(LGWR)・プロセスにより、REDOログ・バッファ内に残されたREDOログ・エントリがオンラインREDOログに書き込まれ、さらにトランザクションのSCNがオンラインREDOログに書き込まれます。これが、トランザクションのコミットを構成するアトミック・イベントです。
Oracle Databaseにより、行と表に対して保持されているロックが解放されます。
未コミットのトランザクションによって保持されているロックを待機してエンキューされていたユーザーが、作業を続行できるようになります。
Oracle Databaseにより、セーブポイントが削除されます。
表10-1では、sal_update
トランザクション内にセーブポイントが存在しないため、消去されたセーブポイントはありません。
Oracle Databaseにより、コミットのクリーンアウトが実行されます。
コミットされたトランザクションのデータが含まれている変更済ブロックが引き続きSGA内に存在し、このブロックを変更する他のセッションがない場合は、データベースにより、このブロックからロックに関するトランザクション情報が削除されます。COMMIT
でブロックをクリーンアウトし、後続のSELECT
によるこのタスクの実行を不要にすると理想的です。
トランザクションをコミットした後、ユーザーは変更を表示できます。
通常のコミットは、トランザクションのサイズにかかわらず高速な操作です。コミットの速度は、トランザクション内で変更されるデータのサイズによって遅くなりません。コミットで最も時間がかかる部分は、LGWRによって実行される物理ディスクI/Oです。ただし、LGWRではREDOログ・バッファの内容が段階的にバックグラウンドで書き込まれるため、LGWRにかかる時間は削減されます。
デフォルトの動作では、LGWRによりREDOがオンラインREDOログに同時に書き込まれ、トランザクションはバッファ内のREDOがディスクに移動するまで待機してから、コミットをユーザーに戻します。ただし、アプリケーション開発者は、トランザクションのコミット待機時間を短縮するために、REDOが非同期に書き込まれ、REDOがディスクに移動されるまでトランザクションが待機せずに、COMMIT
コールからすぐに戻れるよう指定できます。
自律型トランザクションは、メイン・トランザクションと呼ばれる他のトランザクションからコールできる独立したトランザクションです。コール側のトランザクションを一時停止して、自律型トランザクション内でSQL操作を実行し、その操作をコミットまたは取り消してから、コール側トランザクションを再開できます。
自律型トランザクションは、コール側トランザクションでコミットまたはロールバックするかどうかに関係なく、独立して実行する必要があるアクションを実装する場合に便利です。たとえば、株購入のトランザクションでは、全体的な株購入が成立するかどうかにかかわらず、顧客データをコミットする必要があります。また、トランザクション全体がロールバックされた場合でも、デバッグ表にエラー・メッセージを記録することも必要となります。
自律型トランザクションの特性は、次のとおりです。
自律型トランザクションでは、メイン・トランザクションによって加えられたがコミットされていない変更は取り扱わず、ロックやリソースをメイン・トランザクションと共有することもありません。
自律型トランザクション内の変更は、自律型トランザクションのコミット時に他のトランザクションに表示されるようになります。そのため、ユーザーはメイン・トランザクションのコミットを待機しなくても更新情報にアクセスできます。
自律型トランザクションで他の自律型トランザクションを開始できます。自律型トランザクションをコールできるレベル数には、リソース制限以外の制限はありません。
PL/SQLでは、自律型トランザクションは自律型スコープ内で実行されます(自律型スコープとは、プラグマAUTONOMOUS_TRANSACTION
でマークされたルーチンです)。このコンテキストでは、トップレベルの無名PL/SQLブロックおよびPL/SQLサブプログラムとPL/SQLトリガーが、ルーチンに含まれています。プラグマは、コンパイラにコンパイル・オプションの実行を指示するディレクティブです。プラグマAUTONOMOUS_TRANSACTION
によって、このプロシージャは実行時に親トランザクションから独立した新しい自律型トランザクションとして実行する必要があることが、データベースに指示されます。
図10-2に、制御がメイン・ルーチン(MT)から自律型ルーチンに移り、再びメイン・ルーチンに戻ってくるまでのフローを示します。メイン・ルーチンはproc1
、自律型ルーチンはproc2
です。自律型ルーチンでは、制御がメイン・ルーチンに戻る前に、複数のトランザクション(AT1およびAT2)をコミットできます。
自律型ルーチンの実行可能セクションに入ると、メイン・ルーチンが一時停止します。この自律型ルーチンを終了すると、メイン・ルーチンが再開されます。
図10-2では、proc1
内部のCOMMIT
により、この文自体の作業のみでなく、そのセッション内で実行されたすべての保留中の作業が確定されます。ただし、proc2
内のCOMMIT
では、proc2
トランザクション内で実行された作業のみが確定されます。したがって、トランザクションAT1およびAT2内のCOMMIT
文は、MTトランザクションに影響を与えません。
関連項目: 自律型トランザクションの使用方法の詳細は、『Oracle Databaseアドバンスト・アプリケーション開発者ガイド』および『Oracle Database PL/SQL言語リファレンス』を参照してください。 |
分散データベースは、分散システム内のデータベースの集合であり、アプリケーションには1つのデータソースとして認識されます。分散トランザクションとは、データベース・リンクと呼ばれるスキーマ・オブジェクトを使用し、分散データベースの複数の異なるノード上でデータを更新する、1つ以上の文を含むトランザクションのことです。データベース・リンクは、1つのデータベース・インスタンスが別のデータベース・インスタンスにログインする様子を記述します。
ローカル・データベースでのトランザクションとは異なり、分散トランザクションでは、複数データベース上にあるデータが変更されます。その結果、データベースではトランザクションでの変更のコミットやロールバックをアトミックな単位として処理する必要があるため、分散トランザクション処理はより複雑になります。トランザクション全体をコミットまたはロールバックする必要があります。Oracle Databaseはネットワーク全体でトランザクション制御を調整し、ネットワーク障害やシステム障害が発生した場合にもデータ整合性が保たれるようにする必要があります。
関連項目: 『Oracle Database管理者ガイド』 |
2フェーズ・コミット・メカニズムは、分散トランザクションに関係するすべてのデータベースが、そのトランザクション内の文のすべてをコミットするか、すべてを取り消すかのどちらか一方のみになるように保証するものです。このメカニズムでは、整合性制約、リモート・プロシージャ・コールおよびトリガーによって実行される暗黙的DMLも保護されます。
複数データベース間の2フェーズ・コミットでは、1つのデータベースで分散トランザクションが調整されます。開始ノードはグローバル・コーディネータと呼ばれます。このコーディネータによって、他のデータベースでコミットの準備ができているかどうかが確認されます。いずれかのデータベースで否定のレスポンスがあった場合は、トランザクション全体がロールバックされます。すべてのデータベースから肯定のレスポンスがあった場合は、コーディネータからメッセージがブロードキャストされ、各データベース上でコミットが確定されます。
2フェーズ・コミット・メカニズムは、分散トランザクションを発行するユーザーからは意識されません。事実、ユーザーは、トランザクションが分散していることも認識する必要はありません。トランザクションの終了を示すCOMMIT
文は、自動的に2フェーズ・コミット・メカニズムをトリガーします。データベース・アプリケーション本体に分散トランザクションを含めるのに、コーディングや複雑な構文の記述は必要ありません。
関連項目: 2フェーズ・コミットの詳細は、『Oracle Database管理者ガイド』を参照してください。 |
インダウト分散トランザクションは、システム障害やネットワーク障害によって2フェーズ・コミットが中断されたときに発生します。たとえば、2つのデータベースから調整データベースにコミットの準備ができたことが報告されたものの、このメッセージの受信直後に調整データベース・インスタンスが失敗した場合などです。この場合、コミットの準備ができている2つのデータベースはハング状態となり、結果の通知を待機し続けます。
リカバラ(RECO
)・バックグラウンド・プロセスでは、インダウト分散トランザクションの結果が自動的に解決されます。障害が修復され、通信が再確立された後、各ローカルのOracleデータベースのRECO
プロセスが、関係するすべてのノード上でインダウト分散トランザクションを自動的にコミットするか、ロールバックします。
長時間にわたる障害が発生した場合、Oracle Databaseでは、各ローカル管理者が障害によって発生したインダウト分散トランザクションを手動でコミットまたは取り消すことができます。このオプションにより、ローカル・データベース管理者は、長時間にわたる障害によって無期限にロックされる可能性のあるリソースを解放できます。
あるデータベースを過去のある時点までリカバリする必要がある場合、データベースのリカバリ機能を使用すると、他のサイトのデータベース管理者が、自分のデータベースを過去のその同じ時点に戻すことができます。この操作により、グローバル・データベースは一貫した状態に保たれます。