Oracle Database 管理者ガイド 11gリリース1(11.1) E05760-03 |
|
この章の内容は次のとおりです。
分散トランザクションは1つ以上の文からなり、それらが個別に、またはグループとして、分散データベースの複数ノードのデータを更新します。たとえば、図32-1に示すデータベース構成を考えます。
scott
によって実行される次の分散トランザクションは、ローカルのsales
データベース、リモートのhq
データベース、およびリモートのmaint
データベースを更新します。
UPDATE scott.dept@hq.us.acme.com SET loc = 'REDWOOD SHORES' WHERE deptno = 10; UPDATE scott.emp SET deptno = 11 WHERE deptno = 10; UPDATE scott.bldg@maint.us.acme.com SET room = 1225 WHERE room = 1163; COMMIT;
分散トランザクションでは、次の2種類の操作が許可されます。
分散トランザクションでサポートされているデータ操作言語(DML)およびデータ定義言語(DDL)操作は、次のとおりです。
DML文およびDDL文はパラレルに実行でき、ダイレクト・ロード・インサート
文はシリアルに実行できます。ただし、次の制限に注意してください。
SELECT
文である必要があります。
INSERT
、UPDATE
またはDELETE
文のtable_expression_clauseで参照される表がリモートの場合、実行はパラレルではなくシリアルになります。
インサート
の発行後にリモート操作を実行することはできません。
SELECT
以外の分散操作を実行する場合、DMLはパラレル化されません。
サポートされているトランザクション制御文は、次のとおりです。
分散トランザクションで文が発行されると、データベースはトランザクションに参加しているすべてのノードのセッション・ツリーを定義します。セッション・ツリーとは、セッション間の関係とセッションのロールを表す階層モデルです。セッション・ツリーの例を図32-2に示します。
分散トランザクションのセッション・ツリーに参加しているすべてのノードは、次に示すロールを1つ以上持ちます。
分散トランザクションのノードが果たすロールは、次の条件によって決まります。
情報を別のノードのデータベースから参照するとき、ノードはクライアントとして機能します。参照先のノードはデータベース・サーバーです。図32-2のノードsales
は、warehouse
データベースおよびfinance
データベースが稼働しているノードのクライアントです。
データベース・サーバーは、クライアントがデータを要求する要求先データベースが稼働しているノードです。
図32-2では、sales
ノードのアプリケーションは、warehouse
ノードおよびfinance
ノードのデータにアクセスする分散トランザクションを開始します。したがって、sales.acme.com
はクライアント・ノードのロールを持ち、warehouse
およびfinance
はどちらもデータベース・サーバーのロールを持ちます。この例では、sales
はデータベース・サーバーとクライアントを兼務しています。これは、アプリケーションがsales
データベースのデータも変更するためです。
自身の分散トランザクション部分を完了するために他のノードのデータを参照する必要があるノードのことを、ローカル・コーディネータと呼びます。図32-2では、sales
は自身が直接参照しているwarehouse
ノードおよびfinance
ノードを調整するので、ローカル・コーディネータになります。ノードsales
はまた、トランザクションに関係するすべてのノードを調整することから、グローバル・コーディネータにもなります。
ローカル・コーディネータは、自身が直接やり取りするノードの間で次のようにトランザクションを調整する役目を果たします。
分散トランザクションの実行元であるノードのことを、グローバル・コーディネータと呼びます。分散トランザクションを発行するデータベース・アプリケーションは、グローバル・コーディネータとして機能しているノードに直接接続します。たとえば、図32-2では、ノードsales
で発行されたトランザクションは、データベース・サーバーwarehouse
およびfinance
の情報を参照します。したがって、sales.acme.com
は、この分散トランザクションのグローバル・コーディネータになります。
グローバル・コーディネータは、セッション・ツリーの親またはルートになります。グローバル・コーディネータは、分散トランザクション処理中に次の操作を実行します。
コミット・ポイント・サイトの役割は、グローバル・コーディネータの指示に従ってコミットまたはロールバックの操作を開始することです。システム管理者は、すべてのノードにコミット・ポイント強度を割り当てることで、セッション・ツリー内のノードの1つをコミット・ポイント・サイトとして必ず指定します。コミット・ポイント・サイトには、最も重要なデータを格納するノードを選択してください。
図32-3は、sales
がコミット・ポイント・サイトとして機能している分散システムの例です。
コミット・ポイント・サイトは、分散トランザクションに関係する他のすべてのノードと次の点で区別されます。
分散トランザクションは、コミット・ポイント以外のすべてのサイトで準備が完了した後、コミットされたとみなされますが、実際には、トランザクションはコミット・ポイント・サイトで先にコミットされています。コミット・ポイント・サイトのREDOログは、このノードで分散トランザクションがコミットされるとただちに更新されます。
コミット・ポイント・ログにはコミットの記録があります。そのため、たとえ参加中のノードの一部がまだ準備完了状態であり、それらのノードで実際にトランザクションがコミットされていない場合であっても、トランザクションはコミットされたとみなされます。同様の意味で、コミット・ポイント・サイトでコミットがまだログに記録されていない場合には、分散トランザクションはコミットされていないとみなされます。
データベース・サーバーには、必ずコミット・ポイント強度を割り当てる必要があります。データベース・サーバーが分散トランザクション内で参照される場合、そのコミット・ポイント強度の値によって、2フェーズ・コミットにおける役割が決まります。具体的には、このコミット・ポイント強度によって、どのノードが分散トランザクションのコミット・ポイント・サイトになり、他のすべてのノードより前にコミットするかが決まります。この値を指定するには、初期化パラメータCOMMIT_POINT_STRENGTH
を使用します。ここでは、データベースがコミット・ポイント・サイトを決定する仕組みについて説明します。
準備フェーズの冒頭で決定されるコミット・ポイント・サイトは、トランザクションに参加しているノードの中からのみ選択されます。次に示す一連のイベントが発生します。
図32-4は、各ノードのコミット・ポイント強度(かっこ内の値)を示したセッション・ツリーの例です。また、コミット・ポイント・サイトとして選択されたノードも示しています。
コミット・ポイント・サイトを決定するときは、次の条件が適用されます。
ROLLBACK
文をすべてのノードに送り、分散トランザクションの処理を終了します。
図32-4のように、コミット・ポイント・サイトとグローバル・コーディネータがセッション・ツリーの異なるノードになることもあります。各ノードのコミット・ポイント強度は、最初に接続が確立されたときにコーディネータに渡されます。コーディネータは、2フェーズ・コミット時のコミット・ポイント・サイトを効率的に選択するために、自身が直接やり取りしている各ノードのコミット・ポイント強度を保持しています。そのため、コミットが発生するたびにコーディネータとノード間でコミット・ポイント強度を交換する必要がありません。
関連項目:
|
ローカル・データベースのトランザクションとは異なり、分散トランザクションには複数のデータベースでのデータの変更が伴います。そのため、データベースは、トランザクションの変更のコミットまたはロールバックを自己完結単位として調整する必要があり、分散トランザクションの処理はより複雑になります。言い換えれば、トランザクション全体がコミットするか、またはトランザクション全体がロールバックするかのどちらかの結果になります。
データベースは、2フェーズ・コミット・メカニズムを使用することで、分散トランザクションにおけるデータの整合性を保証します。準備フェーズでは、トランザクション内の開始ノードが他の参加ノードに対して、トランザクションをコミットまたはロールバックすることを確約するように要求します。コミット・フェーズでは、開始ノードがすべての参加ノードに対して、トランザクションをコミットするように要求します。この結果が達成できない場合、すべてのノードはロールバックするように要求されます。
分散トランザクションに参加しているすべてのノードは、必ず同じ動作を実行します。つまり、ノードすべてがトランザクションをコミットするか、またはノードすべてがトランザクションをロールバックします。データベースは、分散トランザクションのコミットまたはロールバックを自動的に制御および監視しており、2フェーズ・コミット・メカニズムを使用してグローバル・データベース(トランザクションに参加しているデータベースの集まり)の整合性を維持します。このメカニズムは完全に透過的であり、ユーザーやアプリケーション開発者の側でプログラミングを行う必要はまったくありません。
コミット・メカニズムは、次の各フェーズで構成されています。データベースは、ユーザーが分散トランザクションをコミットすると、必ずこれらのフェーズを自動的に実行します。
この項の内容は、次のとおりです。
準備フェーズは、分散トランザクションのコミットにおける1番目のフェーズです。このフェーズでは、データベースがトランザクションを実際にコミットまたはロールバックすることはありません。ここでは、分散トランザクションで参照されているすべてのノード(「コミット・ポイント・サイト」で説明されているコミット・ポイント・サイトを除く)がコミットを準備するように指示されます。ノードは、準備を完了するために次の処理を実行します。
各ノードは、コミットの準備が完了したという応答をグローバル・コーディネータに伝えることによって、その後トランザクションをコミットまたはロールバックすることを確約します。しかし、トランザクションをコミットまたはロールバックするという決定を各ノードが一方的に下すわけではありません。この確約の意味は、この時点でインスタンス障害が発生した場合、ノードはオンライン・ログのREDOレコードを使用してデータベースをリカバリし、準備フェーズに戻すことができるということです。
注意: ノードの準備完了後に発行した問合せは、すべてのフェーズが完了するまで、関連するロック済みデータにアクセスできません。この時間は、障害が発生しないかぎり問題にはなりません(「インダウト・トランザクションの処理方法の決定」を参照)。 |
準備を指示されたノードは、次の方法で応答できます。
応答 | 意味 |
---|---|
準備完了 |
ノードのデータの変更が分散トランザクション内の文によって完了しており、ノードの準備が正常に完了しています。 |
読取り専用 |
ノードで変更されるデータがない(問合せのみ)か、または変更できないので、準備は不要です。 |
異常終了 |
ノードが正常に準備できません。 |
ノードの準備が正常に完了すると、ノードは準備完了メッセージを発行します。このメッセージは、ノードの変更レコードがオンライン・ログに格納されており、ノードでコミットまたはロールバックのどちらかを実行できる準備が整っていることを示します。また、このメッセージによって、トランザクションに対して保持されているロックが障害発生時にも残ることが保証されます。
ノードが準備を要求されたときに、データベースにアクセスするSQL文がノードのデータを変更しない場合、ノードは読取り専用メッセージで応答します。このメッセージは、ノードがコミット・フェーズに参加しないことを示します。
分散トランザクションの全部または一部が読取り専用になるケースとして、次の3つがあります。
分散トランザクションが読取り専用に設定されている場合、そのトランザクションでUNDOセグメントは使用されません。多数のユーザーがデータベースに接続していて、ユーザーのトランザクションがREAD ONLY
に設定されていない場合は、それらのトランザクションが問合せを実行するのみであっても、UNDO領域が割り当てられます。
ノードは、正常に準備できないときに次の処理を実行します。
これらの処理は、分散トランザクションに関係している他のノードに伝播します。これにより、他のノードはトランザクションをロールバックできるので、グローバル・データベースのデータの整合性が保証されます。この応答によって、「トランザクションに関係しているすべてのノードが同じ論理時間ですべてコミットするかまたはすべてロールバックする」という分散トランザクションの基本原則が守られます。
準備フェーズを完了するために、コミット・ポイント・サイトを除く各ノードは次の手順を実行します。
これらの処理によって、ノードが後で自身のトランザクションをコミットまたはロールバックできることが保証されます。この後、準備完了ノードは、グローバル・コーディネータからCOMMIT
またはROLLBACK
要求を受け取るまで待機します。
各ノードの準備が完了した後、分散トランザクションはインダウトと呼ばれる状態になります(「インダウト・トランザクション」を参照)。分散トランザクションは、すべての変更がコミットまたはロールバックされるまで、インダウト状態のままです。
コミット・フェーズは、分散トランザクションのコミットにおける2番目のフェーズです。このフェーズになる前に、分散トランザクションで参照されるコミット・ポイント・サイト以外のすべてのノードが準備を完了していること、つまり、コミット・ポイント・サイト以外のすべてのノードがトランザクションのコミットに必要なリソースを確保していることが保証されます。
コミット・フェーズは次の手順で構成されています。
コミット・フェーズが完了するときは、分散システムの全ノードのデータについて一貫性が保たれています。
コミットされた各トランザクションには、そのトランザクション内部のSQL文によって行われた変更を一意に識別するためのSCNが対応付けられます。SCNは、データベースのコミット済バージョンを一意に識別する内部的なタイムスタンプの役割を持ちます。
分散システムでは、次の処理がすべて発生したときに、通信中のノードのSCNが調整されます。
特に、分散システムのノード間でSCNが調整されることにより、文とトランザクションの両方のレベルでグローバルな読込み一貫性が保証されるという利点があります。必要であれば、グローバルな時間ベースのリカバリを実行することもできます。
準備フェーズ時に、データベースは、トランザクションに関係しているすべてのノードで最も高いSCNを判断します。次に、コミット・ポイント・サイトにおいて最も高いSCNでトランザクションをコミットします。さらに、すべての準備完了ノードに対して、コミットの指示とともにコミットSCNを送ります。
参加ノードが自身のコミットの完了をコミット・ポイント・サイトに通知した後、コミット・ポイント・サイトは、トランザクションに関する情報を消去できます。次の手順が発生します。
2フェーズ・コミット・メカニズムは、すべてのノードがコミットされるかまたはロールバックを一斉に実行することを保証します。システムやネットワークのエラーのために、3つのフェーズのいずれかが失敗した場合はどうなるのでしょうか。この場合、トランザクションはインダウトになります。
分散トランザクションは、次の要因によってインダウトになる可能性があります。
マシン、ネットワークまたはソフトウェアの問題が解決されると、RECOプロセスによってインダウト・トランザクションが自動的に解決されます。RECOがトランザクションを解決できるまで、データは読取りおよび書込みの両方についてロックされます。読取りをブロックするのは、データベースが問合せに対してどのバージョンのデータを表示すればよいかを判断できないためです。
この項の内容は、次のとおりです。
データベースでは、多くの場合、インダウト・トランザクションは自動的に解決されます。たとえば、次の使用例においてlocal
とremote
の2つのノードがあるとします。ローカル・ノードはコミット・ポイント・サイトです。ユーザーscott
は、local
に接続してlocal
とremote
を更新する分散トランザクションを実行し、コミットします。
図32-5は、分散トランザクションの準備フェーズ中に障害が発生したときの一連のイベントを示しています。
次の手順が発生します。
SCOTT
はLocal
に接続して分散トランザクションを実行します。
remote
データベースが、local
に準備応答を発行する前にクラッシュします。
図32-6は、分散トランザクションのコミット・フェーズ中に障害が発生したときの一連のイベントを示しています。
次の手順が発生します。
Scott
はlocal
に接続して分散トランザクションを実行します。
remote
から受け取ります。
remote
に送ってコミットを要求します。
remote
データベースはコミット・メッセージを受け取りましたが、ネットワーク障害のために応答できません。
次の場合のみ、インダウト・トランザクションを手動で解決する必要があります。
インダウト・トランザクションの解決が複雑になる場合があります。その場合は、次の手順を実行する必要があります。
DBA_2PC_PENDING
ビューおよびDBA_2PC_NEIGHBORS
ビューを問い合せ、トランザクションに関係しているデータベースのコミットが完了しているかどうかを確認します。
COMMIT FORCE
文を使用してコミットを強制実行するか、またはROLLBACK FORCE
文を使用してロールバックを強制実行します。SCNは、コミット済みバージョンのデータベースの内部的なタイムスタンプです。Oracle Databaseサーバーは、SCNクロック値を使用することでトランザクションの一貫性を保証します。たとえば、ユーザーがトランザクションをコミットするとき、データベースはそのコミットのSCNをREDOログに記録します。
データベースは、SCNを使用して、異なるデータベース間での分散トランザクションを調整します。たとえば、データベースは、次のときにSCNを使用します。
SCNは、トランザクションが失敗した場合も含め、トランザクションの同期化されたコミット・タイムスタンプとして機能するため、分散トランザクションにとって非常に重要な存在です。トランザクションがインダウトになった場合、管理者はこのSCNを使用して、グローバル・データベースへの変更を調整できます。トランザクション・コミットのグローバルSCNは、分散リカバリの実行時など、後でトランザクションの識別に使用することもできます。
この使用例では、ある会社がsales.acme.com
およびwarehouse.acme.com
という異なるOracle Databaseサーバーを持っています。ユーザーが売上レコードをsales
データベースに挿入すると、対応付けられたレコードがwarehouse
データベースで更新されます。
この分散処理の事例では、次のことを示します。
営業部門で、営業担当がSQL*Plusを使用して売上注文を入力し、コミットします。アプリケーションは次のようなSQL文を発行し、sales
データベースに注文を入力して、warehouse
データベースのinventory表を更新します。
CONNECT scott@sales.acme.com ...; INSERT INTO orders ...; UPDATE inventory@warehouse.acme.com ...; INSERT INTO orders ...; UPDATE inventory@warehouse.acme.com ...; COMMIT;
これらのSQL文は単一の分散トランザクションの一部であり、発行されるすべてのSQL文がユニットとして成功または失敗することが保証されています。文をユニットとして扱うことにより、注文が設定されているにもかかわらず、注文を反映するように在庫が更新されていないという事態を防ぐことができます。実際は、トランザクションによってグローバル・データベースのデータの一貫性が保証されています。
トランザクションの各SQL文が実行されると、図32-7のようにセッション・ツリーが定義されます。
トランザクションの次の点に注意してください。
sales
データベースで実行されている注文入力アプリケーションです。したがって、分散トランザクションのグローバル・コーディネータは、sales.acme.com
になります。
sales
データベースに挿入し、warehouseデータベースのinventory表を更新します。したがって、ノードsales.acme.com
とwarehouse.acme.com
はどちらもデータベース・サーバーになります。
sales.acme.com
はinventory表を更新するため、warehouse.acme.com
のクライアントになります。
この段階では、この分散トランザクションのセッション・ツリーの定義が完了します。ツリー内の各ノードは、必要なデータ・ロックを獲得して、ローカル・データを参照するSQL文を実行します。これらのロックは、SQL文の実行が完了した後も、2フェーズ・コミットが完了するまで保持されます。
データベースは、COMMIT
文の直後にコミット・ポイント・サイトを判別します。図32-8のように、グローバル・コーディネータのsales.acme.com
がコミット・ポイント・サイトとして判別されます。
準備段階では、次の手順が実行されます。
warehouse.acme.com
のみです。
warehouse.acme.com
は準備を試みます。トランザクション内のローカルに独立した部分をコミットし、自身のローカルREDOログにコミット情報を記録できることをノードが保証できれば、そのノードは正常に準備できます。この例では、sales.acme.com
がコミット・ポイント・サイトなので、warehouse.acme.com
のみが準備メッセージを受け取ります。
warehouse.acme.com
は、準備完了メッセージでsales.acme.com
に応答します。
各ノードが準備を終えると、準備を要求した側のノードに応答メッセージが送り返されます。応答に応じて、次のいずれかの動作が発生します。
コミット・ポイント・サイトによるトランザクションのコミットでは、次の手順が実行されます。
sales.acme.com
は、warehouse.acme.com
の準備が完了しているという確認を受け取り、トランザクションをコミットするようにコミット・ポイント・サイトに指示します。
warehouse.acme.com
がまだコミットを完了していない場合でも、このトランザクションの結果は事前に決まっています。つまり、対象となるノードのコミットが遅れた場合でも、トランザクションはすべてのノードでコミットされます。
この段階では、次の手順が実行されます。
トランザクション内のすべてのノードによるトランザクションのコミットでは、次の手順が実行されます。
図32-10では、コミット・ポイント・サイトとグローバル・コーディネータを兼務しているsales.acme.com
が、トランザクションのローカルのコミットをすでに完了しています。この時点でsales
はwarehouse.acme.com
に対してトランザクションのコミットを指示します。
トランザクションのコミットの完了は、次の手順で実行されます。
COMMIT
フェーズの完了後、分散トランザクションそのものが完了します。これまで説明した手順は、1秒以内に自動的に実行されます。