不会。CouchDB 使用“乐观并发”模型。用最简单的术语来说,这仅意味着您随更新一起发送文档版本,如果当前文档版本与您发送的版本不匹配,CouchDB 将拒绝更改。
这确实很简单。您可以为 CouchDB 重新构建许多基于正常事务的场景。不过,在学习 CouchDB 时,您确实需要放弃 RDBMS 领域知识。从更高的层次解决问题比尝试将 Couch 塑造成基于 SQL 的世界更有帮助。
跟踪库存
您所描述的问题主要是库存问题。如果您有一个描述某个项目的文档,并且它包含“可用数量”字段,您可以像这样处理并发问题:
- 检索文档,记下
_rev
CouchDB 发送的属性
- 如果数量字段大于零,则减少数量字段
- 使用以下命令发回更新后的文档
_rev
财产
- If the
_rev
与当前存储的数字匹配,完成!
- 如果有冲突(当
_rev
不匹配),检索最新的文档版本
在这种情况下,需要考虑两种可能的故障场景。如果最新文档版本的数量为 0,您可以像在 RDBMS 中一样处理它,并提醒用户他们实际上无法购买他们想要购买的东西。如果最新的文档版本的数量大于 0,您只需使用更新的数据重复该操作,然后从头开始。这迫使您比 RDBMS 做更多的工作,并且如果存在频繁的冲突更新,可能会有点烦人。
现在,我刚才给出的答案假设您将在 CouchDB 中执行操作,其方式与在 RDBMS 中执行操作的方式大致相同。我可能会以不同的方式处理这个问题:
我将从一个“主产品”文档开始,其中包含所有描述符数据(名称、图片、描述、价格等)。然后,我将为每个特定实例添加一个“库存票”文档,其中包含以下字段product_key
and claimed_by
。如果您要销售一种型号的锤子,并且有 20 个要出售,您可能会拥有包含以下钥匙的文档:hammer-1
, hammer-2
等,代表每个可用的锤子。
然后,我将创建一个视图,为我提供可用锤子的列表,并使用减少功能让我看到“总计”。这些完全是即兴的,但应该让您了解工作视图的样子。
Map
function(doc)
{
if (doc.type == 'inventory_ticket' && doc.claimed_by == null ) {
emit(doc.product_key, { 'inventory_ticket' :doc.id, '_rev' : doc._rev });
}
}
这为我提供了按产品密钥列出的可用“门票”列表。当有人想买锤子时,我可以抓住其中的一组,然后迭代发送更新(使用id
and _rev
)直到我成功领取一张(之前领取的门票将导致更新错误)。
Reduce
function (keys, values, combine) {
return values.length;
}
这个reduce函数只是返回无人认领的总数inventory_ticket
物品,这样您就可以知道有多少“锤子”可供购买。
Caveats
该解决方案需要您对所提出的特定问题进行大约 3.5 分钟的整体思考。可能有更好的方法来做到这一点!也就是说,它确实大大减少了更新冲突,并减少了响应新更新冲突的需要。在此模型下,不会有多个用户尝试更改主要产品条目中的数据。在最糟糕的情况下,您将有多个用户尝试领取一张票,如果您从您的视野中抓住了其中几张票,您只需转到下一张票并重试即可。
参考:https://wiki.apache.org/couchdb/Frequently_asked_questions#How_do_I_use_transactions_with_CouchDB.3F https://wiki.apache.org/couchdb/Frequently_asked_questions#How_do_I_use_transactions_with_CouchDB.3F