知识卡片
2PC协调者失效导致存疑事务与持锁阻塞的运维代价
内容
2PC最大的运维隐患出在协调者故障:若协调者在发送准备请求前崩溃,参与者可以安全中止;但一旦参与者已经投了”是”,就进入”存疑”(不确定)状态——它已经承诺可以提交,却不知道最终结果是提交还是中止,只能死等协调者恢复,超时机制在这里完全帮不上忙(单方面提交或中止都可能与其他参与者的最终结果不一致)。而参与者在存疑期间必须继续持有它读写过的行级锁(甚至共享读锁),这意味着如果协调者20分钟才恢复,这些锁就要被拿着20分钟;若协调者日志彻底丢失,锁可能被永久持有,直到管理员手动介入用”启发式决策”打破——但这本质上是承认可能违反原子性的紧急逃生舱口,不是常规手段。这暴露了2PC的深层问题:协调者本身就是一种关键数据库,若它不像数据库一样被小心地复制和持久化,就会成为整个系统的单点故障,能把远比协调者本身重要得多的业务系统一并拖入不可用。
结构图:
sequenceDiagram
participant App as 应用
participant Coord as 协调者
participant DB1 as 参与者1
participant DB2 as 参与者2
App->>Coord: 请求提交
Coord->>DB1: 准备请求
Coord->>DB2: 准备请求
DB1-->>Coord: 是(承诺可提交,持锁)
DB2-->>Coord: 是(承诺可提交,持锁)
Note over Coord: 决定提交,写入磁盘日志(不归路)
Coord--xDB1: 提交请求(协调者此时崩溃,未送达)
Coord->>DB2: 提交请求
Note over DB1: 存疑状态,持锁等待,超时无法自行决定
参考来源
- 位置:《数据密集型应用系统设计》第九章《一致性与共识》"协调者失效""怀疑时持有锁""从协调者故障中恢复"(源文件:_epub-src/ch9_split_001.html)
- 结论依据:原文描述参与者投"是"后进入存疑状态、必须持锁等待协调者恢复,超时无法安全解决,并说明协调者日志丢失时锁可能被永久持有、只能靠启发式决策打破,直接支撑本卡片结论及时序图。
- 原始内容:参与者收到了准备请求并投了"是",就不能再单方面放弃……在事务提交或中止之前,数据库不能释放这些锁……如果协调者的日志由于某种原因彻底丢失,这些锁将被永久持有。