首页 > 解决方案 > 2阶段提交实现

问题描述

我正在尝试在文档数据库上实现两阶段提交,该文档数据库使用插入数据的事务信息仅支持单阶段提交。

我了解两阶段提交背后的理论,但在实践中存在一些障碍。

假设有一个定义了唯一 ID 的集合,事务包括更新文档的多个字段。所以为了在回滚的情况下保存旧数据,我不能覆盖现有文档,而是需要添加一个新文档并用事务ID标记它:

解决方案1:

准备阶段:

  1. 使用更新的字段将新文档插入主集合,并用当前事务 ID 标记它。
  2. 在提交之前将旧文档标记为已删除,并用当前事务 ID 标记它。

提交阶段:

  1. 从添加的(更新的)文档中删除事务 ID。
  2. 删除旧文档(标记为已删除)

问题:准备阶段的第 1 部分将失败,因为我正在添加另一个具有相同唯一 ID 的文档(尽管它只是为了交易,但它仍然会失败)。

解决方案2:

准备阶段:

  1. 将新文档插入到具有更新字段的临时集合中,并用当前事务 ID 标记它。
  2. 将主集合中的旧文档标记为已删除,直到提交并使用当前事务 ID 标记它。

提交阶段:

  1. 将新文档从临时集合移动到主集合。
  2. 从主集合中删除旧文档(标记为已删除)。

问题:如果在将文档从临时集合移动到主集合时存在唯一键冲突,则提交阶段第 1 部分可能会失败。
但是,我不能允许在提交阶段发生此错误,因为为时已晚,我希望唯一键约束在准备阶段失败。

那么实施 2 阶段提交机制并避免这些问题的正确方法是什么?

标签: transactionsunique-keydocument-database2phase-commit

解决方案


推荐阅读