假设我有一个名为“products”的couchDB数据库和一个带有表单的前端。 现在,如果用户以我希望阻止其他用户编辑此特定文档的形式从此数据库打开文档。
通常非常简单:
-> read document from couchDB
-> set a variable to true like: { edit : true }
-> save (merge) document to couchDB
-> if someone else tries to open the document he will receive an error, becaus of edit:true.
但是,如果两个用户在同一时间打开文档怎么办? 该函数将被调用两次,当第二个函数打开文档时,他将错误地接收编辑:false,因为第一个没有足够的时间来保存他的编辑:true。那么如何防止这种行为?
首先解决方案是: 构建一个数组作为数据库请求的提示,并且不允许并行请求,因此所有请求将一个接一个地处理掉。但在我看来,这是一个糟糕的解决方案,因为系统在某些时候会变得令人难以置信。
第二种解决方案: 将当前编辑的文档的documentID存储在脚本中的本地数组中。这可以工作,因为这不是异步过程,第二个用户会立即收到他的错误。
到目前为止这么好,但是,如果某天有太多用户并且这个系统应该在集群(节点客户端服务器,而不是数据库)中运行,那么现在第二个解决方案将不再起作用,因为每个集群都是将拥有自己的documentID数组。在那里共享将以另一个异步任务结束,并导致上述相同的问题。
现在我没有想法,大型集群系统通常如何处理这类问题?
答案 0 :(得分:2)
CouchDB使用MVCC来保持数据库的一致性。更新文档时,您必须同时提供ID(_id
)和修订号(_rev
),否则您的更改将被拒绝。
这意味着如果2个客户端在修订版1中读取文档并且两个客户端都尝试使用相同的修订版号编写更改,则数据库只接受第一个版本。第二个客户端将收到错误,它应该获取文档的最新版本以继续。
在单节点环境中,此模型可以完全防止冲突。但是,在发生复制的情况下,即使使用MVCC,仍然可能会发生冲突。这是因为冲突的修订在技术上可以在它们彼此复制之前写入不同的节点。在这种情况下,CouchDB将记录冲突,您的应用程序负责解决它们。
CouchDB拥有出色的文档,特别是他们an article all about conflicts and replication我强烈推荐这个主题。