我正在尝试获取完整的图片... 当我创建 session 时,我知道与此 session 关联的所有写入操作将一起成功或一起回滚。
我没有找到任何官方的 mongo 文档来解释到底什么事务会加锁,以及在事务的生命周期内什么时候会发生加锁(这里的锁我指的是悲观锁或乐观锁)
post here seems基于文档锁定在文档更新并在 session 结束时释放后开始的假设。
但是文档是否需要锁定?真的就在那一瞬间锁定了吗?我在哪里可以找到相关文档?
这意味着如果我这样做
const person = await findOne({ id },{ session })
const updatedPerson = await updateOne({ id },{ person },{ session , new: true})
session
位于 findOne
上绝对没有任何意义?因为特定的 person
文档没有被锁定?
因此,如果在我找到此人并更新此人之间,其他某个请求已更新 Person
,则 updatedPerson
实际上可能与 person
不同, 那是对的吗?没有以 session 方式构建 mongoDB 来确保 person
被锁定? (我知道有一个用于 optimisticConcurrency 的模式选项,但我想了解 session ,而且此选项似乎仅限于仅抛出错误而不是重试,考虑到通常的行为,这似乎有点奇怪您想要的 optimisticConcurrency 是重试或至少可以选择)
如果这是正确的,那么 session
进行严格读取
操作的唯一原因是能够查看写入
结果是 session 的一部分。
const updatedPerson = await updateOne({ id },{ field1: 'changed' },{ session , new: true})
const person = await findOne({ id} ,{ session })
在此处将 person
与 session
关联可以让我查看 updatedPerson
帖子更新。
我的理解正确吗?如果是这样,那就引出了下一个问题,特别是关于带有 .save()
的 Mongoose 。根据mongoose documentation
For example, if you're using save() to update a document, the document can change in MongoDB in between when you load the document using findOne() and when you save the document using save() as show below. For many use cases, the save() race condition is a non-issue. But you can work around it with findOneAndUpdate() (or transactions) if you need to.
这提出了我的问题,考虑到事务不锁定读取文档,如何修复事务的 save()
竞争条件?
最佳答案
我使用 await new Promise((r) => setTimeout(r, 5000));
进行了一些手动测试并在 session 正在进行时更新文档以观察其行为。
我的发现如下:
在此示例中:
const person = await findOne({ id },{ session })
const updatedPerson = await updateOne({ id },{ $set: { ...person } },{ session , new: true})
session
有含义上findOne
,尽管findOne
操作不会锁定文档,它会导致 updateOne
如果 findOne
获取的文档则失败并中止事务,在我们的例子中person
,被不属于交易一部分的某些内容所更改。
这意味着您可以相信 updatedPerson
将是person
因为person
是 session 的一部分。这个答案使我的问题的其余部分变得无关紧要。
关于node.js - MongoDB,网上没有关于事务和读操作交互的信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70055372/