**二阶段提交**（英語：）是指在计算机网络以及数据库领域内，为了使基于分布式系统架构下的所有节点在进行事务提交时保持一致性而设计的一种演算法。通常，**二阶段提交**也被称为是一种**协议**（Protocol）。在分布式系统中，每个节点虽然可以知晓自己的操作时成功或者失败，却无法知道其他节点的操作的成功或失败。当一个事务跨越多个节点时，为了保持事务的ACID特性，需要引入一个作为**协调者**的组件来统一掌控所有节点（称作**参与者**）的操作结果并最终指示这些节点是否要把操作结果进行真正的提交（比如将更新后的数据写入磁盘等等）。因此，二阶段提交的算法思路可以概括为： 参与者将操作成败通知协调者，再由协调者根据所有参与者的反馈情报决定各参与者是否要提交操作还是中止操作。

需要注意的是，**二阶段提交**（英語：）不应该与并发控制中的**二阶段锁**（英語：）混淆。

前提
--

二阶段提交算法的成立基于以下假设：

1. 该分布式系统中，存在一个节点作为**协调者**（），其他节点作为**参与者**（）。且节点之间可以进行网络通信。
2. 所有节点都采用预写式日志，且日志被写入后即被保持在可靠的存储设备上，即使节点损坏不会导致日志数据的消失。
3. 所有节点不会永久性损坏，即使损坏后仍然可以恢复。

基本算法
----

以下对**二阶段提交**算法分阶段进行说明。

### 第一阶段（提交请求）

1. 协调者节点向所有参与者节点询问是否可以执行提交操作，并开始等待各参与者节点的响应。
2. 参与者节点执行询问发起为止的所有事务操作，并将Undo信息和Redo信息（英语：）写入日志。
3. 各参与者节点响应协调者节点发起的询问。如果参与者节点的事务操作实际执行成功，则它返回一个"同意"消息；如果参与者节点的事务操作实际执行失败，则它返回一个"中止"消息。

有时候，第一阶段也被称作**投票阶段**，即各参与者投票是否要继续接下来的提交操作。

### 第二阶段（提交执行阶段）

#### 成功

当协调者节点从所有参与者节点获得的响应消息都为"同意"时：

1. 协调者节点向所有参与者节点发出"正式提交"的请求。
2. 参与者节点正式完成操作，并释放在整个事务期间内占用的资源。
3. 参与者节点向协调者节点发送"完成"消息。
4. 协调者节点收到所有参与者节点反馈的"完成"消息后，完成事务。

#### 失败

如果任一参与者节点在第一阶段返回的响应消息为"终止"，或者协调者节点在第一阶段的询问超时之前无法获取所有参与者节点的响应消息时：

1. 协调者节点向所有参与者节点发出"回滚操作"的请求。
2. 参与者节点利用之前写入的Undo信息执行回滚，并释放在整个事务期间内占用的资源。
3. 参与者节点向协调者节点发送"回滚完成"消息。
4. 协调者节点收到所有参与者节点反馈的"回滚完成"消息后，取消事务。

有时候，第二阶段也被称作**完成阶段**，因为无论结果怎样，协调者都必须在此阶段结束当前事务。

### 算法示意

下述流程图简单示意了二阶段提交算法中协调者和参与者之间的通信流程

```
    -{zh-hans:协调者;zh-hant:協調者;}-                                              -{zh-hans:参与者;zh-hant:參與者;}-
                              QUERY TO COMMIT
                -------------------------------->
                              VOTE YES/NO           prepare*/abort*
                <-------------------------------
commit*/abort*                COMMIT/ROLLBACK
                -------------------------------->
                              ACKNOWLEDGMENT        commit*/abort*
                <--------------------------------  
end

```

"\*" 所标记的操作意味着此类操作必须记录在稳固存储（英语：）上.

缺点
--

二阶段提交算法的最大缺点就在于它的执行过程中间，节点都处于阻塞状态。即节点之间在等待对方的响应消息时，它将什么也做不了。特别是，当一个节点在已经占有了某项资源的情况下，为了等待其他节点的响应消息而陷入阻塞状态时，当第三个节点尝试访问该节点占有的资源时，这个节点也将连带陷入阻塞状态。

另外，协调者节点指示参与者节点进行提交等操作时，如有参与者节点出现了崩溃等情况而导致协调者始终无法获取所有参与者的响应信息，这时协调者将只能依赖协调者自身的超时机制来生效。但往往超时机制生效时，协调者都会指示参与者进行回滚操作。这样的策略显得比较保守。

二阶段协议的实现
--------

### 通用架构

一般情况下，2PC协议都应用在分布式计算机网络中。通过实现多个相同的2PC组件，可以实现一个分布式的协议。该组件一般称为事务处理器 (TMs，或者2PC代理以及事务处理监视器)，该组件负责推进各事务节点执行协议（例如X/Open XA）。分布式事务内的涉及的所有数据库，包括参与者、协调者均注册到附近的TMs（一般和事务参与者处于相同的网络节点中），从而可以通过2PC来完成相关事务。每一个分布式事务都属于他们所注册的TMs。每一个事务都有一个领导者，即协调者TM，用来管理2PC协议。基于性能和可靠性考虑，协调者角色可以转移到其他的TM节点上。各参与者之间并不直接进行协议通信，参与者只会和协调者进行消息通信，由协调者负责推进各参与者执行协议。通过这种架构，该协议完全是分布式的（因为不依赖任何中心节点或者数据结构），也可以根据业务规模横向扩展。
这种通用架构对于除了2PC的其他分布式原子提交协议也是适用的，因为所有此类协议都使用相同的投票机制，并将结果广播给协议的参与者。

### 协议优化

通过假设一些特定的系统行为，可以实现一些方案来优化协议。既能够获得两阶段提交协议的收益，同时能够减少协议操作所消耗的时间。

#### 假定回滚和假定提交

#### 树型二阶段提交协议

关联条目
----

* X/Open XA
* 三阶段提交

参照
--

1. ↑  C. Mohan, Bruce Lindsay and R. Obermarck (1986): "Transaction management in the R\* distributed database management system" （页面存档备份，存于）,*ACM Transactions on Database Systems (TODS)*, Volume 11 Issue 4, Dec. 1986, Pages 378 - 396
2. 1 2  Hadzilacos, Vassos; Goodman, Nathan.. Reading, Mass.: Addison-Wesley Pub. Co. 1987. ISBN 0-201-10715-5. OCLC 13793504.
3. 1 2  Vossen, Gottfried.. San Francisco: Morgan Kaufmann. 2002. ISBN 0-585-45682-8. OCLC 52610193.
4. ↑  Philip A. Bernstein, Eric Newcomer (2009): *Principles of Transaction Processing*, 2nd Edition 的存檔，存档日期2010-08-07. Chapter 8, Morgan Kaufmann (Elsevier), ISBN 978-1-55860-623-4