ECP リカバリの簡単な例は、一時的なネットワーク接続の中断が発生した場合です。この場合の中断時間は、その発生を検知できるほどには長いが、基本の TCP 接続を維持する上では問題ない程度に短いと考えます。この障害が発生している間、アプリケーション・サーバは、接続が応答しないことを検知するため、その接続に対する新しいネットワーク要求をブロックします。接続が再開すると、ブロックされていた処理は中断していた要求を送信できるようになります。
アプリケーション・サーバは、接続が再確立されると、削除するロックのキューとロールバックするトランザクションを保持します。このキューを保持することにより、中断中のトランザクションやロックがあるデータ・サーバが現在利用可能かどうかにかかわらず、アプリケーション・サーバのプロセスはいつでも停止できます。ECP リカバリでは、データ・サーバのキューに入れられた中断中の Set 処理と Kill 処理をすべて完了してから、ネットワーク障害が検出され、ロックの解放が完了します。
ECP リカバリ保証
ECP 構成システムのリカバリ中、InterSystems IRIS は以下のリカバリを保証します。
各保証についての説明では、最初に具体的な状況を説明します。その後に、その状況に適用できるデータ保証について説明します。
これらの説明では、Process A、Process B などは、データ・サーバでグローバルを更新しようとするプロセスを参照します。これらのプロセスは、同じアプリケーション・サーバまたは異なるアプリケーション・サーバ、あるいはデータ・サーバ自体で生成される可能性があります。プロセスの起源が指定される場合もあれば、関係しない場合もあります。
更新順の保証
Process A が 2 つのデータ要素を続けて更新したとします。最初にグローバル ^x を、次にグローバル ^y を更新します。このとき、^x と ^y は、同じデータ・サーバにあります。
Process B は ^y への変更を確認できる場合、^x への変更も確認できます。これは、Process A と Process B が同じアプリケーション・サーバ上にあるかどうかにかかわらず、2 つのデータ・アイテムが同じデータ・サーバにあり、データ・サーバが起動している限り保証されます。
Process B が Process A によって変更されたデータを表示できるからといって、Process A からの Set オペレーションの後に、Process B からの Set オペレーションがリストアされることが保証されるわけではありません。クラスタのフェイルオーバー時またはクラスタのリカバリ時に 2 つの異なるプロセスからの Set や Kill オペレーションが競合する場合、適切な順序を保証できるのは、Lock または $Increment オペレーションのみです。
クラスタのデジャーナル時とクラスタのフェイルオーバー時に異なるプロセスからの Set と Kill オペレーションが競合している場合に適用される順序については、"クラスタのフェイルオーバー時やリストア時の緩やかな順序" の制限を参照してください。
Important:
この保証は、データ・サーバがクラッシュした場合、^x と ^y がジャーナルされている場合でも、適用されません。この説明に該当するプロセスで、データ・サーバがクラッシュする以前に保存されなかったダーティ・データが読み取れるケースについては、"ECP でのロックしないダーティ・データの読み取り" 制限を参照してください。
ECP ロックの保証
Process B (DataServer S 上) が、Process A によってロックされたことがあるグローバル ^x のロックを取得したとします。
Process B は、(^x へのロックを保持している間) Process A によって行われたすべての更新を DataServer S で表示できますまた、Process C が、(^x へのロックを保持している間) Process B によって行われた更新をDataServer S で表示した場合、Process C は、(^x へのロックを保持している間) Process A によって行われた更新も DataServer S で表示することが保証されます。
このシリアル化機能は、Process A、Process B、Process C が同じアプリケーション・サーバ、または DataServer S 自体に属するかどうかにかかわらず、DataServer S がその間常に起動している限り保証されます。
Important:
保護されるロックとデータは、同じデータ・サーバ上にある必要があります。
クラスタ・ロックの保証
クラスタ・メンバの Process B が、Process A によってロックされたことがあるクラスタ・データベースのグローバル ^x へのロックを取得したとします。
この場合、Process B は、(^x へのロックを取得している間、) Process A によっていずれかのクラスタ・データベースに行われたすべての更新を表示できます。
また、クラスタ・メンバの Process C が、(^x へのロックを取得した場合、) Process B によってクラスタ・データベースに行われた更新を表示できるだけでなく、Process C は、(^x へのロックを保持した状態で、) Process A によっていずれかのクラスタ・データベースに行われた更新も表示できます。
このシリアル化機能は、Process A、Process B、Process C が同じクラスタ・メンバに属すかどうか、またはクラスタ・メンバがクラッシュしているかどうかにかかわらず保証されます。
ロールバックの保証
Process A が、一連の更新の後に、TStart コマンドを実行してから、TCommit を発行する前に中断したか、TCommit を実行する前に TRollback を実行したとします。
Process A により、トランザクションの一部として行われた更新はすべて、最初とは逆の順序でロールバックされます。
コミットの保証
Process A が DataServer S で一連の更新を行い、TCommit の実行を開始した後に中断したとします。
トランザクションに含まれる DataServer S それぞれで、DataServer S でのデータの変更がコミットまたはロールバックされます。TCommit を実行するプロセスの Perform Synchronous Commit プロパティがオンになっている場合に (構成ファイル内で SynchCommit=1 に設定)、TCommit オペレーションから正常に値が返されると、そのトランザクションは、トランザクションの一部であるすべてのデータ・サーバで確実にコミットされたことが保証されます。
Important:
トランザクションに複数のサーバ (ローカル・サーバを含む) に対する更新が含まれており、TCommit が正常に完了できないと、トランザクションに含まれるサーバによっては、更新をコミットしたものと、ロールバックしたものがある場合があります。
トランザクションとロックの保証
Process A では Transaction T のために TStart を実行し、DataServer S でグローバル ^x をロックした後、^x をロック解除します (ロック解除しても、“即時アンロック” ロック・タイプは指定されません)。
InterSystems IRIS では、^x へのロックは、トランザクションがコミットされるかロールバックされるまで解除されないことが保証されます。Transaction T が DataServer S でコミットするか、ロールバックするまで、他のプロセスは、^x へのロックを取得できません。
Transaction T が DataServer S でコミットすると、Process B では、^x へのロックを取得し、Transaction T の間に、Process A によって DataServer S に行われた変更が表示されます。また、他のプロセスが、(^x へのロックを保持している間) Process B によって DataServer S に行われた変更を表示した場合、(Transaction T 実行中に) Process A によって DataServer S に行われた変更が表示されます。逆に、Transaction T が DataServer S でロールバックした場合、^x へのロックを取得した Process B が、Process A によって DataServer S に行われた変更を表示しようとしても、何も表示されません。
ECP Rollback Only の保証
Process A (AppServer C 上) が、Transaction T の一部である変更を DataServer S で行い、DataServer S が一方的にその変更をロールバックします (これは、特定のネットワーク障害やデータ・サーバ障害で発生する場合がある)。
その後 Process A による DataServer S に対するネットワーク要求はすべて、Process A が明示的に TRollback コマンドを実行しない限り、<NETWORK> エラーによって拒否されます。
また、AppServer C のプロセスが、DataServer S のロールバックと Transaction T の TCommit の間に、DataServer S へのネットワーク要求を完了した場合 (AppServer C が TCommit の前に rollback-only 条件を検出した場合)、Transaction T には、Transaction T の一部であるすべてのデータ・サーバにロールバックが行われることが保証されます
ECP トランザクション・リカバリの保証
データ・サーバが、アプリケーション・サーバのトランザクションの途中でクラッシュし、その後再起動して、アプリケーション・サーバのリカバリ・タイムアウト時間内にリカバリを完了します。
この場合、トランザクションは、保証されているとおりに、正常に完了できます。データ・サーバは、ロック定義によって定義されている順番の制約に違反するようなデータ処理は実行しません。唯一の例外は、$Increment 関数です (詳細は、"ECP とクラスタの $Increment 制限" を参照してください)。リカバリできないトランザクションは、ロック定義を保護するようにロールバックされます。
Important:
(ネットワーク、データ・サーバ、アプリケーション・サーバのハードウェアやソフトウェアなどで) 障害が継続して発生していない場合、InterSystems IRIS では、データ・サーバ停止時にデータ・サーバで未実行のすべてのあるいは大半のトランザクションは復元できるはずです。しかし、これは保証されません。
ECP ロック・リカバリの保証
DataServer S に計画外のシャットダウンが発生したため、再起動して、リカバリ時間内にリカバリを完了しました。
この場合、ECP ロックの保証は、変更されたデータがジャーナルされている限り適用されます。データがジャーナルされていない場合、クラッシュの前のデータ・サーバに対する更新は、アプリケーション・サーバに通知されることなく、失われます。InterSystems IRIS では、ロックを取得したプロセスが、そのロックを保持している間に、他のプロセスによって以前に行われたすべての更新を表示できることは保証されません。
DataServer S を正しくシャットダウンし、再起動し、リカバリ時間内にリカバリを完了した場合は、データがジャーナルされているかどうかにかかわらず、ECP ロックの保証は適用されます。
トランザクションの一部である更新は、常にジャーナルされ、ECP トランザクション・リカバリの保証は確実に適用されます。他のジャーナルは、目的のデータベース内のグローバルがジャーナリングとマークされているかどうかによって、ジャーナルされる場合とされない場合があります。
$Increment 順序の保証
$Increment 関数には、異なるプロセスからの Set や Kill オペレーションがロックで保護されていなくても、それらの一連のオペレーションに対する緩やかな順序があります。
例えば、Process A が、DataServer S で、Set と Kill オペレーションを実行し、DataServer S でグローバル ^x に $Increment オペレーションを実行します。Process B は、その後に、同じグローバル ^x に $Increment を実行します。Process B を含むどのプロセスからでも、^x をインクリメントした Process B の結果を表示する場合、^x をインクリメントする前に Process A が DataServer S に実行したすべての変更も表示されます。
ECP Sync メソッドの保証
プロセス A は、データ・サーバ S にあるグローバルを更新し、$system.ECP.Sync() 呼び出しを S に対して発行します。続いて、プロセス B は $system.ECP.Sync() を S に対して発行します。プロセス B は、$system.ECP.Sync() 呼び出しの前に、プロセス A がデータ・サーバ S で実行したすべての更新を表示できます。
$system.ECP.Sync() は、アプリケーション・サーバで実行しているプロセスにのみ関係があります。プロセス A または B のいずれかがデータ・サーバ S 自体で実行している場合、そのプロセスは $system.ECP.Sync() を発行する必要はありません。両方のプロセスがデータ・サーバ S で実行している場合、どちらも $system.ECP.Sync を必要としません。これは、同じサーバで実行しているプロセスがグローバル更新を直ちに見ることができることを示す文に過ぎません。
ECP リカバリの制限
ECP 構成システムのリカバリ中、InterSystems IRIS の保証には以下の制限があります。
ECP とクラスタの $Increment 制限
データ・サーバに対する未実行 $Increment 要求がアプリケーション・サーバにあり、グローバルがジャーナリングされたとき、データ・サーバがクラッシュすると、InterSystems IRIS は、$Increment 結果をジャーナルから回復しようとし、参照を再びインクリメントしません。
ECP Cache の最新性の制限
障害が継続して発生していない場合は、アプリケーション・サーバは数秒以内にデータの更新を参照できますが、これは保証されていません。特に、ECP のデータ・サーバとの接続が中断した場合 (ネットワーク障害、データ・サーバのシャットダウン、データ・サーバのバックアップ処理など)、ユーザ・プロセスはアプリケーション・サーバの接続タイムアウト値を限度に古いデータを参照する場合があります。データが古くないことを確認するには、Lock コマンドをデータ・フェッチ操作で使用するか、または $system.ECP.Sync を使用します。アプリケーション・サーバとデータ・サーバ間を往復するネットワーク要求によって、アプリケーション・サーバ ECP ネットワーク・キャッシュのコンテンツが更新されます。
ECP ルーチンの再検証の制限
アプリケーション・サーバがデータ・サーバからルーチンをダウンロードして、データ・サーバが (計画的または計画外に) 再起動されると、データ・サーバからダウンロードされたルーチンは編集済みであるかのようにマークされます。
また、データ・サーバとの接続にネットワーク障害 (アプリケーション・サーバかデータ・サーバのシャットダウン) が発生した場合も、データ・サーバからダウンロードされたルーチンは編集済みであるかのようにマークされます。この動作は、場合によっては、実体を伴わない <EDITED> エラーや <ERRTRAP> エラーが発生させることがあります。
非ロック状態の変更により競合が発生した場合のロールバック
InterSystems IRIS では、Lock コマンドはアドバイスに過ぎません。Process A が、グローバル ^y へのロックが保護された状態で、グローバル ^x を更新するトランザクションを開始し、別のプロセスが、^y へのロックが保護されていない状態で、^x を変更した場合、^x のロールバックは機能しません。
Set と Kill オペレーションのロールバックでは、データ・アイテムの現在の値がオペレーションによって設定された値である場合、その値は、オペレーションの前の値にリセットされます。現在の値が Set や Kill オペレーションによって設定された値とは異なる場合、現在の値は変更されません。
データ・アイテムが、ある時点でトランザクションの内部で変更され、別の時点でトランザクションの外部で、Lock コマンドで保護されずに変更されるような場合は、ロールバック機能は保証されません。ロールバックを有効にするには、データ・アイテムを変更する場合に必ずロックを使用する必要があります。
ジャーナルが中断した場合のロールバック
ロールバックは、ジャーナルの信頼性と完全性に依存しています。ジャーナルのデータが何かによって中断された場合、その中断した時点以降のロールバックは行えません。InterSystems IRIS では、このようなトランザクションのロールバックは暗黙的に無視されます。
ジャーナルの中断が発生する可能性がある場合は、InterSystems IRIS の動作中に ^JRNSTOP を実行した場合、InterSystems IRIS がシャットダウンした後や再起動する前に Write Image Journal (WIJ) ファイルを削除した場合、またはジャーナルのエラー時にシステムをフリーズするように設定されていないシステムで、ジャーナリング中に入出力エラーが発生した場合です。
ECP のリカバリ後に検出されないエラー
Set や Kill オペレーションが、データ・サーバで完了した後、エラーが発生したとします。データ・サーバはそのパケットの処理は完了していますが、アプリケーション・サーバ・システムに送信する前にクラッシュします。
この場合、ECP リカバリではそのパケットを再生しませんが、アプリケーション・サーバはそのエラーを検出していないため、アプリケーション・サーバは、データ・サーバ側の Set または Kill オペレーションを失います。
部分的 Set または Kill によるジャーナルの不一致
Set や Kill オペレーションを問題なくジャーナルできても、実際にデータベースを変更する前にエラーが発生するケースがあります。データのロールバックを定義する特別な方法があっても、それによって、トランザクションのロールバックが行われなくなることはありませんが、ジャーナルのリストア後のデータベースの状態は、リストア前のデータベースの状態と一致しなくなる場合があります。
クラスタのフェイルオーバーまたはリストア時の緩やかな順序
クラスタのデジャーナリングは緩やかに順序付けられます。異なるクラスタ・メンバのジャーナル・ファイルが同期化されるのは、ロック、$Increment、またはジャーナル・マーカー・イベントが発生した場合のみです。これは、クラスタ全体を停止してリストアする必要があるクラスタのフェイルオーバーやクラスタのクラッシュ後のデータベース状態に影響します。その場合、データベースは、クラッシュ前の状態と異なる状態にリストアされる場合があります。$Increment 順序の保証には、リストアされたデータベースがクラッシュ前の元の状態と異なる度合いに関する新たな制約があります。
Process B が Process A によって変更されたデータを表示できるからといって、Process A からの Set オペレーションの後に、Process B からの Set オペレーションがリストアされることが保証されるわけではありません。クラスタのフェイルオーバー時またはクラスタのリカバリ時に 2 つの異なるプロセスからの Set や Kill オペレーションが競合する場合、適切な順序を保証できるのは、Lock または $Increment オペレーションのみです。
クラスタ・メンバのクラッシュ時のダーティ・データの読み取り
クラスタ・メンバ Member A が Transaction T1 で更新を完了し、そのトランザクションが非同期のトランザクション・コミット・モードでコミットされたとします。別のクラスタ Member B の Transaction T2 が、Transaction T1 によって所有されていたロックを取得したとします。そして、Transaction T1 からのすべての情報がディスクに書き込まれる前に、クラスタ・メンバ Member A がクラッシュしたとします。
この場合、Transaction T1 は、クラスタ・フェイルオーバーの一部としてロールバックされます。しかし、Member B の Transaction T2 では、ロック・プロトコルの規則に従って、Transaction T1 の情報を表示できたはずであるのに、後でクラスタ・フェイルオーバーの一部としてロールバックされています。また、Transaction T2 で Transaction T1 と同じデータ・アイテムが一部変更された場合、Transaction T1 のロールバックは、一部のトランザクション・データしかロールバックできないため、失敗する可能性があります。
これを回避する方法は、クラスタ・メンバ Member A のトランザクションを同期コミット・モードで行うことです。同期コミット・モードを使用した場合、Transaction T1 はロックが解除される前にディスクに保存され、アプリケーションが Transaction T1 が完全であることを認識すれば、ロールバックされることはありません。
ECP でのロックしないダーティ・データの読み取り
ECP トランザクションがロックしないでデータを読み取る場合、ディスクに保存されていないデータを読み取りますが、データ・サーバがクラッシュするとそのデータは失われる可能性があります。そのようなデータを読み取れるのは、他の ECP 接続やローカル・データ・サーバ・システム自体によって、データの場所が設定されている場合のみです。保存されていないデータが、その接続自体によって設定されている場合は表示できません。また、データを読み取るプロセスとデータを書き込むプロセスの両方にロックが使用されている場合、保存されていないデータを表示することはできません。ここでは、更新順の保証が適用されず、ロックを使用する以外に簡単に解決できる方法はありません。
非同期のエラーが TCommit で検出された場合のロールバック
データ・サーバ側のトランザクションが、データベースの更新中に、<FILEFULL> などの非同期のエラー状況に遭遇し、アプリケーション・サーバが TCommit 時までそのエラーを認識できなかった場合、トランザクションは自動的にデータ・サーバ側でロールバックされます。ただし、TCommit オペレーションは通常は非同期ですが、ロールバックは同期です。これは、アプリケーション・サーバ・プロセスがロックを解除するまでにアプリケーション・サーバに通知しておく必要があるブロックが、ロールバックによって変更されるためです。
データ・サーバとデータベースには問題はありませんが、アプリケーション・サーバ側では、ロックが別のプロセスに移った場合、アプリケーション・サーバはロールバックされようとするデータを一時的に参照する場合があります。しかし、アプリケーション・サーバでは、非同期エラーを発生させることを通常は行いません。