1. ホーム
  2. database

二相コミット

2023-11-16 16:05:28

質問

2PC (two-phase commit protocol)とは何か、Javaやほとんどのモダンな言語でどのように使用するのか、ほとんどの人が知っていると思います。基本的には、2つ以上のDBを持っているときに、トランザクションが同期していることを確認するために使用されます。

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

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

AはコミットしているがBはコミットしていない、2PCを使っていることを思い出してください(だから、2PCの設計が機能しなくなるんですね)。

どのように解決するのですか?

二相コミットについて

二相コミットは分散トランザクションが失敗しないことを保証するものではありませんが、TMに気づかれずに黙って失敗することがないことを保証するものです。

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

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

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

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

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

アプリケーションはまだエラーから回復できなければなりませんが、アプリケーションが不整合状態に気づかないまま、トランザクションが静かに失敗することはありえません。

セマンティクス

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

  • フェーズ2でリソースマネージャやネットワークが停止した場合、トランザクションマネージャは トランザクション・マネージャーは、リソース・マネージャーが復旧するまで ポーリングし続けます。 リソース・マネージャに再接続されると RMにトランザクションをコミットするように指示します。 RMが「Unknown」というエラーを返した場合 が「Unknown TxID」というエラーを返した場合、TMは以下のことを認識します。 RM でデータ損失の問題が発生したことを認識します。

  • フェーズ 1 で TM が停止した場合、クライアントは TM が復旧するまでブロックされます。 TM が復旧するまでブロックします。 ただし、タイムアウトするか、ネットワーク接続の切断によりエラーが発生した場合はこの限りではありません。 この場合、クライアントはエラーを認識します。 この場合、クライアントはエラーを認識し、再試行するか、自ら中止を開始することができます。

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

リソースマネージャにおけるコミット後のデータ損失イベントは、トランザクションマネージャでは処理されず、RMのレジリエンスの機能として処理されます。

二相コミットはフォールトトレランスを保証するものではありません。 Paxos を参照してください。しかし、分散トランザクションの部分的な失敗が気付かれないようにすることは保証されます。

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