【问题标题】:How to avoid cyclic dependencies between documents in CouchDB如何避免 CouchDB 中文档之间的循环依赖
【发布时间】:2011-03-12 21:48:47
【问题描述】:

我对 CouchDB 中文档之间的关系建模很感兴趣。假设我有三个文档 A、B 和 C。这些文档可以相互引用,但是有一个应用程序约束,不能发生循环依赖。

举个例子(-> 是依赖的标记):

A -> B

C

两个客户端(C1、C2)尝试并发修改:

C1 = B -> C

C2 = C -> A

如果 C1 和 C2 成功,就会有循环。问题是如何预防?

我正在考虑它,似乎我需要一种用于文档和原子批量更新的粗粒度锁。问题是原子批量更新。 CouchDB 支持批量更新,但在版本冲突的情况下不回滚。什么意思:

假设我们有文档 V。该文档代表全局版本(粗粒度锁定)并保存给定文档修订版本的相关文档(A、B、C)的版本。

V {
  _rev: 1,
  versions: [[A,1],[B,1],[C,1]] 
}

C1 和 C2 同时工作:

  1. C1 = 得到 V

  2. C2 = 得到 V

  3. C1 = 获取 A.1、B.1、C1

  4. C2 = 获取 A.1、B.1、C1

  5. C1 = 进行依赖性检查(一切正常)

  6. C2 = 进行依赖性检查(一切正常)

  7. C1 = 根据预期的 B->C 依赖关系更新 V {版本:[[A,1],[B,2],[C,2]] }(一切正常)

  8. C1 = 更新 B

  9. C2 = 尝试更新 V 关于预期的 C->A 依赖 {版本:[[A,2],[B,1],[C,2]] }(此步骤将失败,因为CouchDB 乐观锁)

一切都很好,直到 C1 在第 7 步和第 8 步之间崩溃。现在批量插入/更新即将到来。

7.) C1 = 更新 V 关于预期的 B->C 依赖 {versions: [[A,1],[B,2],[C,2]] }(一切正常)并更新 B

多么好的解决方案,不幸的是它根本不起作用,因为 CouchDB http://wiki.apache.org/couchdb/HTTP_Bulk_Document_API#Transactional_Semantics_with_Bulk_Updates 中的批量插入/更新语义。批量插入/更新不是原子操作。

有什么解决方法吗?我可以以某种方式绕过它吗?我错过了什么重要的事情吗?

【问题讨论】:

    标签: dependencies couchdb nosql


    【解决方案1】:

    如果我可以在这里添加 0.02 美元,关系真的不适用于基于文档的数据库。

    考虑从“参考”的角度重新考虑模型,例如一个文档引用另一个文档,另一个文档引用第一个文档。这对于文档来说是完全正常的,但是来自关系世界的我们都有思维惯性的问题:)

    【讨论】:

      【解决方案2】:

      两个客户端(C1、C2)尝试并发 修改:

      C1 = B -> C

      C2 = C -> A

      如果 C1 和 C2 成功,将会有 循环。问题是如何预防 是吗?

      这是无法避免的。如果 C1 与服务器 X 合作,C2 与服务器 Y 合作,而 X 和 Y 未连接到网络上,该怎么办。当 X 和 Y 重新连接和复制时,文档 B 和 C 最终都将被编辑。

      当我们说 CouchDB 在单个文档上是事务性的时,这就是我们的意思。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-11
        • 1970-01-01
        • 2013-02-06
        • 1970-01-01
        • 1970-01-01
        • 2012-02-15
        • 2011-06-16
        相关资源
        最近更新 更多