コンピュータネットワークや分散データベースにおいて、3フェーズコミットプロトコル(3PC)[ 1 ]は、システム内のすべてのノードがトランザクションのコミットまたは中止に同意することを保証する分散アルゴリズムです。これは、コミットフェーズ中の特定の種類の障害によって引き起こされる無期限のブロックの可能性を排除することで、2フェーズコミットプロトコル(2PC)を改善しています。
2段階コミットプロトコルでは、コミットフェーズ中にコーディネーターとコホートメンバーの両方が故障した場合、確実に復旧することはできません。コーディネーターのみが故障し、コホートメンバーがコミットメッセージを受信していない場合は、コミットが行われなかったと安全に推測できます。しかし、コーディネーターとコホートメンバーの両方が故障した場合、故障したコホートメンバーが最初に通知を受け、実際にコミットを実行した可能性があります。新しいコーディネーターが選出されたとしても、すべてのコホートメンバーから同意を得るまでは操作を続行できないため、すべてのコホートメンバーからの応答があるまでブロックする必要があります。
3フェーズコミットプロトコルは、コミット準備完了状態を導入することでこの問題を解消します。コーディネーターがpreCommitメッセージを送信する前に失敗した場合、コホートは全員一致で操作が中止されたことに同意します。コーディネーターは、すべてのコホートメンバーがコミット準備完了状態であることをACKするまで、doCommitメッセージを送信しません。これにより、すべてのコホートメンバーがトランザクションを完了する決定を認識する前に、いずれかのコホートメンバーが実際にトランザクションを完了してしまう可能性がなくなります(これは、 2フェーズコミットプロトコルで無期限のブロックを必要としていた曖昧さでした)。
上記で紹介したプリコミットフェーズは、コミットフェーズ中に参加者、またはコーディネーターと参加者の両方が失敗した場合に、システムの復旧を支援します。2フェーズコミットのコミットフェーズ中にコーディネーターが失敗した後にリカバリコーディネーターが引き継ぐ場合、新しいプリコミットは次のように役立ちます。参加者に問い合わせて、一部のノードがコミットフェーズにあることがわかった場合、クラッシュする前のコーディネーターがコミットを決定したと想定します。したがって、プロトコルをコミットに導くことができます。同様に、参加者がPrepareToCommitメッセージを受信していないと報告した場合、新しいコーディネーターは、前のコーディネーターがPrepareToCommitフェーズを完了する前に失敗したと想定できます。したがって、どの参加者も変更をコミットしていないと安全に想定し、トランザクションを安全に中止できます。
Skeenのオリジナルの3フェーズコミットプロトコルを使用すると、クォーラムが接続されても処理が進まない可能性があります(これはデッドロック状態ではありません。ネットワークの分割が解決されれば、システムは引き続き処理を進めます)。KeidarとDolevのE3PC [ 2 ]は、Skeenの3フェーズコミットプロトコルを改良し、クォーラムが常に処理を進められるようにこの問題を解決します。
3フェーズコミットは、ネットワークの遅延とノードの応答時間が制限されていることを前提としています。ネットワーク遅延や処理の一時停止が無制限であるほとんどの実用システムでは、アトミック性を保証できません。このプロトコルのもう1つの欠点は、完了までに少なくとも3回の往復が必要であり、最低でも3回の往復時間(RTT)が必要となることです。これは、各トランザクションの完了に長い遅延が発生する可能性があることを意味します。