二相コミット
質問
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 を参照してください。しかし、分散トランザクションの部分的な失敗が気付かれないようにすることは保証されます。
- この種の障害は、以前にコミットされたトランザクションからのデータも失う可能性があることに注意してください。 2 フェーズ コミットは、リソース マネージャーがデータを失ったり破損したりしないことや、DR 手順が失敗しないことを保証するものではありません。
関連
-
[解決済み] データベースのインデックスはいくつあっても足りない?
-
[解決済み] SQLITE SQLダンプファイルをPOSTGRESQLに変換する
-
[解決済み] MS Accessの代替となるフリーソフト [終了しました]。
-
[解決済み] 73億行のマーケットデータ(読み出しに最適化)を格納する方法とは?
-
[解決済み] 二相コミットはどのように最後の一秒の失敗を防ぐのか?
-
[解決済み] HiveQLクエリの結果をCSVに出力するにはどうしたらいいですか?
-
[解決済み] 大きなデータベース」って何?[クローズド]
-
[解決済み] 私はCouchDBでトランザクションとロックを行うことができますか?
-
[解決済み] ライブデータベースで気をつけるべきことNo.1とは?[クローズド]
-
データミックはいつ使えばいいのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] データベースのインデックスはいくつあっても足りない?
-
[解決済み] SQLite UPSERT / UPDATE OR INSERT
-
[解決済み] データベースに郵便番号を格納する必要があります。カラムの大きさはどのくらいにすればよいでしょうか?
-
[解決済み] DynamoDBからアイテム数を取得するには?
-
[解決済み] 営業時間のデータベースへの格納
-
pg_restore error: role XXX does not exist
-
特にWebアプリケーションで、データベースの行識別子としてUUIDを使用することについて、どう思われますか?
-
データベースで整数カラムの自動インクリメントがmax_valueに達した場合、何が起こりますか?
-
PostgreSQLのパスワードのデータ型は何ですか?
-
コンテキストを必要とするAndroidのユニットテスト