我在mongodb中有一个分片的文档集,还有几个访问它的应用程序服务器。
每个应用程序都提供新文档,最终还需要删除一些文档。
删除哪些文件并不重要,但关键是它删除(声明)一个确切的数字,并且没有其他应用程序正在删除(声明)相同的文档。
我的想法是:
unique = makeUniqueValue()
docs = []
for (i = 0;i < 10;i++) {
r = findAndModify( claim: false, $set: { claim: unique });
if (r.value) docs.push(r);
}
if (docs.length < 10)
"release all docs by updating (claim: false) and try again in some time"
此解决方案的一个潜在问题是,由于应用程序太多(文档很少),他们只会继续声明某些文档并再次发布它们。
这个问题的众所周知且经过充分测试的解决方案是什么?
“update”和“findAndModify”是否保证更新的文档在更新前与查询匹配?
或者另一个应用程序是否可以在匹配和更新之间“窃取”它,因此两个应用程序都认为他们已经声明了该文档?
答案 0 :(得分:1)
在该文档上运行更新后,它将确保查询与文档匹配,并且它是最新版本。
任何其他程序都无法在每个文档的基础上窃取。
为了进一步解释,因为我意识到这个问题很简单:MongoDB在数据库级别上有一个写作者贪婪的读/写锁。
这意味着findAndModify
在写入操作被赋予运行能力时将无法找到某些内容。因此,它无法找到即将在另一个线程/应用程序中声明的文档。
因此,此代码会立即将文档声明隔离到一个应用程序,因为另一个应用程序对循环的每次迭代都会导致无人认领的文档,而MongoDB服务器上永远不会出现中间/部分状态。
实际更新时无关紧要,因为您知道这些文档是您需要更新的文档,但是$set
等运算符在单个文档上按顺序运行,因为更新操作本身不能文档状态要么是claim
false
,要么是空。更新还将直接从数据文件中选取行,而不是从写出的静态结果集中选择行。
如果您使用_id
或其他静态数据进行更新,则会有所不同。