MongoDB,网上没有关于事务和读操作交互的信息
Posted
技术标签:
【中文标题】MongoDB,网上没有关于事务和读操作交互的信息【英文标题】:MongoDB, there is no info online about transactions and read operations interaction 【发布时间】:2021-12-31 10:33:25 【问题描述】:我正在尝试获取完整的图片... 当我创建会话时,我知道与此会话关联的所有写入操作要么一起成功,要么一起回滚。
我没有找到任何官方 mongo 文档来解释确切的事务锁定以及在事务的生命周期内何时发生锁定(通过锁定我指的是悲观锁或乐观锁)
post here seems 是基于这样的假设,即在文档更新并在会话结束时释放后开始锁定。
但是文档甚至需要锁定吗?真的会在那一瞬间锁定吗?我在哪里可以找到这方面的文档?
这意味着如果我这样做了
const person = await findOne( id , session )
const updatedPerson = await updateOne( id , person , session , new: true)
session
在findOne
上绝对没有意义?因为特定的person
文档没有被锁定?
因此,如果在我找到此人并更新此人之间,一些其他请求已更新 Person
、updatedPerson
实际上可能与 person
不同,对吗?会话中没有内置 mongoDB 以确保 person
将被锁定? (我知道optimisticConcurrency
有一个模式选项,但我想了解会话,而且这个选项似乎仅限于仅抛出错误而不是重试,考虑到通常你想要的行为,这似乎有点奇怪optimisticConcurrency 是重试或至少可以选择)
如果这是正确的,那么session
严格执行read
操作的唯一原因是能够查看作为会话一部分的write
结果。
const updatedPerson = await updateOne( id , field1: 'changed' , session , new: true)
const person = await findOne( id , session )
在此处将person
与session
关联让我可以查看updatedPerson
的帖子更新。
我的理解正确吗?如果是这样,这就引出了下一个问题,特别是关于 .save()
的猫鼬。根据mongoose documentation
例如,如果您使用 save() 更新文档,则文档可以更改 在 MongoDB 中,介于使用 findOne() 加载文档和 使用 save() 保存文档,如下所示。对于许多用例,save() 竞赛 条件不是问题。但是您可以使用 findOneAndUpdate() (或 交易),如果你需要的话。
这引发了我的问题,考虑到事务不锁定读取的文档,您如何解决save()
的竞争条件?
【问题讨论】:
你为一个问题提出了太多的问题,尽管我能理解你的疑问,因为文档肯定是缺乏的。如果你想要大局观,你可以找到一些有用的东西here。如果事后仍有不清楚的地方,我建议您用更具体的问题编辑问题。 @MarcoLuzzara 谢谢!尽管它没有回答我的问题,或者至少我无法从那里提供的信息中推断出答案,但它确实让我对幕后发生的事情有了很多了解,我肯定会多次回到这个资源,这是一个非常好的。 很高兴知道你发现它很有用 :) 我忘了告诉你,但也有一些 tests 尤其有助于完全理解WriteConflict
s。
【参考方案1】:
我使用await new Promise((r) => setTimeout(r, 5000));
进行了一些手动测试,并在会话正在进行时更新文档以观察其行为。
我的发现如下:
在这个例子中:
const person = await findOne( id , session )
const updatedPerson = await updateOne( id , $set: ...person , session , new: true)
对于findOne
上的session
有含义,即使findOne
操作没有锁定文档,它也会导致updateOne
失败并中止事务如果由findOne
(在我们的例子中为person
)获取的文档被不属于事务的某些内容所更改。
这意味着您可以相信updatedPerson
将是person
,因为person
是会话的一部分。这个答案使我的其余问题变得无关紧要。
【讨论】:
以上是关于MongoDB,网上没有关于事务和读操作交互的信息的主要内容,如果未能解决你的问题,请参考以下文章