You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB事务读写交互、锁规则及Mongoose save竞争条件解决问询

MongoDB事务与读操作交互逻辑答疑

基础前提:MongoDB事务的锁机制

首先明确官方底层实现逻辑:

  • MongoDB多文档事务默认采用乐观并发控制,不存在默认的读阶段悲观锁
  • 事务内执行写操作时,仅会标记文档的事务写入意向,不会立即加排他锁;真正的文档级排他锁会在事务提交阶段获取,持有到事务提交/回滚完成后立即释放
  • 事务提交时会自动做冲突检测:如果本次事务修改的文档在事务启动后被其他事务修改过,会直接抛出WriteConflict错误,终止提交

问题1解答

1.1 纯读操作传session的作用

你给出的第一段代码逻辑判断是正确的:

const person = await findOne({ id },{ session })
const updatedPerson = await updateOne({ id },{ person },{ session , new: true})

默认配置下,事务内的读操作不会给查询到的文档加任何锁,也不会阻止其他请求修改对应文档,所以确实会出现你担心的「findOne之后updateOne之前,文档被其他请求修改,最终更新结果不符合预期」的问题。MongoDB的session本身没有内置的读文档悲观锁能力,如果需要做读锁定,需要自己手动实现,或者配合optimisticConcurrency的版本号校验使用。

1.2 纯读操作需要关联session的场景

你提到的场景确实是最常见的需要给纯读加session的情况:要读取同session内未提交的写操作结果。

const updatedPerson = await updateOne({ id },{ field1: 'changed' },{ session , new: true})
const person = await findOne({ id} ,{ session })

MongoDB事务的未提交写对其他session完全不可见,只有同session下携带session参数的读操作,才能读到这些未提交的变更。除此之外,另一个需要关联session的场景是需要让读操作使用当前事务的统一快照,保证多次读的结果一致性。


问题2解答

Mongoose通过事务解决save竞争条件的核心依赖两点:

  1. MongoDB事务提交阶段的乐观冲突检测:如果save操作修改的文档,在事务启动后已经被其他请求修改过,提交阶段会直接触发冲突错误,本次事务所有修改都会回滚,不会出现覆盖他人修改的问题
  2. Mongoose内置的事务自动重试逻辑:默认配置下,Mongoose遇到WriteConflict这类可重试的事务错误时,会自动重试整个事务流程,不需要开发者手动实现重试逻辑,符合乐观并发的通用使用预期

内容的提问来源于stack exchange,提问作者TG Person

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 23:09:02