Couchdb 默认是事务性的。 couchdb 中的每个文档都包含一个_rev 键。对文档的所有更新都是针对此 _rev 键执行的:-
- 获取文档。
- 使用 _rev 属性发送它以进行更新。
- 如果更新成功,则说明您已更新文档的最新_rev
- 如果更新失败,则该文档不是最新的。重复步骤 1-3。
查看this answer by MrKurt了解更详细的说明。
couchdb recipies 有一个银行示例,展示了如何在 couchdb 中完成交易。
还有这篇 atomic bank transfers 文章说明了 couchdb 中的事务。
无论如何,所有这些链接的共同主题是,如果您遵循 couchdb 模式来更新 _rev,您的数据库中就不会出现不一致的状态。
哎呀,为了安全起见,我什至可以对 (clientId, filenumber) 索引设置一个唯一约束,以确保不会有相同的文件号用于客户端两次。
所有 couchdb 文档都是唯一的,因为两个文档中的 _id 字段不能相同。查看view cookbook
这很简单:在 CouchDB 数据库中,每个文档都必须有一个唯一的 _id 字段。如果您需要数据库中的唯一值,只需将它们分配给文档的 _id 字段,CouchDB 就会为您强制执行唯一性。
但有一个警告:在分布式情况下,当您运行多个接受写入请求的 CouchDB 节点时,只能保证每个节点或 CouchDB 外部的唯一性。 CouchDB 将允许将两个相同的 ID 写入两个不同的节点。在复制时,CouchDB 将检测到冲突并相应地标记文档。
根据评论编辑
如果您想根据另一个文档的成功插入来增加一个文档中的字段
在这种情况下,您可以使用单独的文档。您插入一个文档,等待成功响应。然后添加另一个文档,如
{_id:'some_id','count':1}
有了这个,您可以设置一个 map reduce 视图来简单地计算这些文档的结果,并且您有一个更新计数器。您所做的只是插入一个新文档以反映插入成功,而不是更新单个文档以进行更新。
我总是遇到这样的情况,即文件插入失败会使数据库处于不一致状态,尤其是在另一个客户端同时成功插入文件的情况下。
好的,我已经描述了如何对单独的文档进行更新,但即使在更新单个文档时,您也可以避免不一致:
- 插入新文件
- 当 couchdb 给出成功消息时 -> 尝试更新计数器。
为什么会这样?
这是因为当您尝试更新update document 时,您必须提供_rev 字符串。您可以将_rev 视为您文档的本地状态。考虑这种情况:-
- 您已阅读要更新的文档。
- 您更改了一些字段。
- 同时另一个请求已经更改了原始文档。这意味着该文档现在有一个新的
_rev
- 但是您请求 couchdb 使用您在第 1 步中读取的
_rev 即stale 更新文档。
- Couchdb 会产生异常。
- 您再次阅读该文档,获取最新的
_rev 并尝试更新它。
因此,如果您这样做,您将始终需要根据文档的最新版本进行更新。我希望这能让事情变得更清楚一些。
注意:
正如 Daniel 所指出的,_rev 规则不适用于批量更新。