74

ほとんどの人は、2PC (2 フェーズ コミット プロトコル) とは何か、Java やほとんどの最新言語での使用方法を知っていると思います。基本的に、2 つ以上の DB がある場合にトランザクションが同期していることを確認するために使用されます。

2 つの異なる場所で 2PC を使用する 2 つの DB (A と B) があるとします。A と B がトランザクションをコミットする準備ができる前に、両方の DB がトランザクション マネージャーに、コミットする準備ができていることを報告します。そのため、トランザクション マネージャーが承認されると、A と B に信号を送り返し、先に進むように伝えます。

ここに私の質問があります: A がシグナルを受信し、トランザクションをコミットしたとしましょう。すべてが完了すると、B も同じことをしようとしますが、誰かが電源ケーブルを抜いて、サーバー全体をシャットダウンさせます。B がオンラインに戻ったとき、B は何をしますか? そして、Bはどのようにそれをしますか?

A はコミットされていますが、B はコミットされておらず、2PC を使用していることを思い出してください (つまり、2PC の設計は機能しなくなりますよね?)

4

3 に答える 3

83

2フェーズコミットについて

2フェーズコミットは、分散トランザクションが失敗しないことを保証するものではありませんが、TMが認識しない限りサイレントに失敗しないことを保証します。

Bがトランザクションをコミットの準備ができていると報告するには、Bはトランザクションを永続ストレージに保持する必要があります(つまり、Bは、トランザクションがすべての状況でコミットできることを保証できる必要があります)。この状況では、Bはトランザクションを永続化していますが、トランザクションマネージャーはBからコミットを完了したことを確認するメッセージをまだ受信していません。

トランザクションマネージャは、Bがオンラインに戻ったときに、Bを再度ポーリングし、トランザクションをコミットするように要求します。Bがすでにトランザクションをコミットしている場合は、トランザクションがコミット済みとして報告されます。Bがまだトランザクションをコミットしていない場合は、すでに永続化されているためコミットし、トランザクションをコミットする立場にあります。

この状況でBが失敗するためには、データまたはログエントリを失うという壊滅的な障害が発生する必要があります。トランザクションマネージャは、Bがコミットの成功を報告しなかったことを認識します。1

実際には、Bがトランザクションをコミットできなくなった場合、Bを取り除いた災害によってデータが失われたことを意味し、TMが認識していないTxIDをコミットするように要求したときに、Bはエラーを報告します。コミット可能な状態にあるとは思わなかった。

したがって、2フェーズ・コミットは、壊滅的な障害の発生を防ぐことはできませんが、障害が見過ごされることを防ぎます。このシナリオでは、Bがコミットできない場合、トランザクションマネージャーはアプリケーションにエラーを報告します。

アプリケーションは引き続きエラーから回復できる必要がありますが、アプリケーションが不整合な状態を認識しない限り、トランザクションはサイレントに失敗することはありません。

セマンティクス

  • リソースマネージャーまたはネットワークがフェーズ1でダウンした場合、トランザクションマネージャーは致命的なエラー(リソースマネージャーに接続できません)を検出し、サブトランザクションを失敗としてマークします。ネットワークが復旧すると、参加しているすべてのリソースマネージャーでトランザクションが中止されます。

  • フェーズ2でリソースマネージャーまたはネットワークがダウンした場合、トランザクションマネージャーはリソースマネージャーが復旧するまでポーリングを続けます。リソースマネージャーに再接続すると、RMにトランザクションをコミットするように指示します。RMが「不明なTxID」の行に沿ってエラーを返した場合、TMはRMにデータ損失の問題があることを認識します。

  • フェーズ1でTMがダウンした場合、ネットワーク接続の切断が原因でタイムアウトまたはエラーを受信しない限り、クライアントはTMが復旧するまでブロックします。この場合、クライアントはエラーを認識し、再試行するか、中止自体を開始できます。

  • TMがフェーズ2でダウンした場合、TMが復旧するまでクライアントをブロックします。トランザクションはすでにコミット可能であると報告されており、TMが復旧するまでブロックされる可能性はありますが、致命的なエラーがクライアントに表示されることはありません。TMは、トランザクションがコミットされていない状態のままであり、RMが復旧したときに、RMをポーリングしてコミットします。

リソースマネージャーでのコミット後のデータ損失イベントは、トランザクションマネージャーによって処理されず、RMの復元力の関数です。

2フェーズコミットはフォールトトレランスを保証しません-フォールトトレランスに対処するプロトコルの例についてはPaxosを参照してください-しかし、分散トランザクションの部分的な障害が気付かれずに進むことができないことを保証します。

  1. この種の失敗は、以前にコミットされたトランザクションからのデータも失う可能性があることに注意してください。2フェーズコミットは、リソースマネージャーがデータを失ったり破損したりしないこと、またはDR手順が失敗しないことを保証するものではありません。
于 2011-09-12T14:39:09.680 に答える
3

あらゆる努力をしても最終的にうまくいかないシナリオは、あなたのシナリオだけではありません。A と B の両方が TM に「コミットする準備ができている」と報告した後、誰かが TM とたとえば B の間の線を抜いたとします。B は TM からのゴーアヘッド (またはノーゴー) を待っていますが、確実に勝ちました。 TM が再接続するまで永遠に待機しないでください (トランザクションに関与する独自のリソースは、明らかな理由により、待機時間全体にわたってロック/アクセス不可のままにする必要があります)。そのため、B が自分の好みに合わせて長時間待たされると、いわゆる「ヒューリスティックな決定」が必要になります。つまり、TM とは独立してコミットまたはロールバックすることを決定します。そのようなヒューリスティックな決定は、TM による実際のコミット決定から逸脱する可能性があることは明らかです。

于 2015-03-31T13:36:21.567 に答える