开发者

How to avoid cyclic dependencies between documents in CouchDB

I'm interesting in modeling relations between documents in CouchDB. Let say that i have three documents A,B and C. These documents may refer to each other, but there is an application constraint that cyclic dependency must not occur.

Lets take a example (-> is a marker for dependency):

A -> B

C

Two clients (C1, C2) try concurrent modification:

C1 = B -> C

C2 = C -> A

If C1 and C2 are succeed there will be cycle. The question is how to prevent it?

I was thinking about it and it seems that i need a kind of coarse grained lock for documents an开发者_Python百科d atomic bulk update. The problem is atomic bulk update. CouchDB supports bulk update, but without rollback in case of version conflict. What it means:

Let say we have document V. This document represents global version (coarse grained lock)and holds version of related documents (A,B,C) for a given document revision.

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

C1 and C2 work concurrently:

  1. C1 = get V

  2. C2 = get V

  3. C1 = get A.1, B.1, C1

  4. C2 = get A.1, B.1, C1

  5. C1 = make dependency check (everything is OK)

  6. C2 = make dependency check (everything is OK)

  7. C1 = update V regarding to intended B->C dependency {versions: [[A,1],[B,2],[C,2]] } (everything is OK)

  8. C1 = update B

  9. C2 = trying update V regarding to intended C->A dependency {versions: [[A,2],[B,1],[C,2]] } (this step will FAIL, because of CouchDB optimistic locking)

Everything is fine and nice until C1 crashes between step 7. and 8. Now the bulk insert/update coming to scene.

7.) C1 = update V regarding to intended B->C dependency {versions: [[A,1],[B,2],[C,2]] } (everything is OK) and update B

What a nice solution, unfortunately it doesn't work at all, because of bulk insert/update semantics in CouchDB http://wiki.apache.org/couchdb/HTTP_Bulk_Document_API#Transactional_Semantics_with_Bulk_Updates. The bulk insert/update is not atomic operation.

Is there any workaround for it? May I bypass it somehow? Did I miss something important?


Two clients (C1, C2) try concurrent modification:

C1 = B -> C

C2 = C -> A

If C1 and C2 are succeed there will be cycle. The question is how to prevent it?

This is not preventable. What if C1 is working against server X, and C2 is working against server Y, and X and Y are not connected on the network. When X and Y are reconnected and replicate, both documents B and C will end up having been edited.

This is what we mean when we say CouchDB is transactional on a single document.


If I may add $0.02 here, relations are really not for the world of document-based databases.

Consider rethinking the model in terms of "reference", as in one document referencing the other, and the other referencing the first. This is perfectly normal for documents, but coming from the relational world we all have problems with thinking inertia :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜