在原子操作中测试和减少? [英] Testing and decrementing in an atomic operation?
问题描述
我刚刚找到了一个令人讨厌的bug,这基本上就是竞争条件。为了论证,我们假设一个非常简单的文档结构,如 {_id:'XXX',金额:100}
。
I have just traced down an annoying bug which is basicly a race condition. For the sake of the argument lets assume a very simple document structure like { _id : 'XXX', amount : 100 }
.
这些文档中有数百个这样的文档存在于一个集合中,并且由多个编写者访问,这些编写者有效地尝试将任何值减少但从不低于0.目前这是通过两个查询完成的:
Hundreds of these these documents exist inside a collection and are accessed by multiple writers which effectively try to lower the amount by any value but never below 0. Currently this is done with two queries:
- 第一个查询确定当前金额。
- 只有当金额大于要减去的金额时,才会触发第二个查询。递减当前金额。
当多个线程同时执行此操作时,这当然容易导致混乱。但有没有办法在原子操作中做到这一点?我在文档中找不到类似 test-and-set
的操作。
This is of course prone to result in a mess when multiple threads do this simultaneously. But is there a way to do this in an atomic operation? I couldn't find anything like a test-and-set
operation in the docs.
如果相关:运行这些操作的代码是运行多个Node.js实例的服务器端JavaScript和 mongodb
npm包。
If its relevant: The code running these operations is serverside JavaScript running with multiple Node.js instances and the mongodb
npm package.
推荐答案
如果金额
大于0,则将更新限定为仅更新文档:
Qualify the update to only update the doc if amount
is greater than 0:
db.coll.update({_id: 'XXX', amount: {$gt: 0}}, {$inc: {amount: -1}})
这篇关于在原子操作中测试和减少?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!