Mongoose更新冲突问题:count字段累加异常求助
问题分析与解决方案
你的问题核心是**乐观并发控制(optimisticConcurrency)**导致的版本冲突,使得第二次save()操作未生效。
原因解释
你开启了optimisticConcurrency: true,Mongoose会自动为文档添加__v版本字段实现乐观锁:
- 调用
findOne获取用户时,本地user对象的__v是当时数据库中的版本号(比如初始为0)。 findOneAndUpdate直接更新数据库文档,同时自动将__v递增(变为1)。- 此时本地
user对象的__v仍为0,与数据库当前版本不匹配。调用save()时,Mongoose会验证版本号,发现不一致则拒绝执行更新,导致第二次累加操作失效,最终count仅增加了1。
解决方案
方案1:统一使用原子更新(推荐)
避免混合使用本地文档修改和直接数据库更新,两次操作都用findOneAndUpdate执行原子递增,彻底规避版本冲突:
async function helper(){ // 从数据库获取用户数据 const user=await User.findOne({username:"ravi"}); console.log(user); // 第一次原子更新 await User.findOneAndUpdate({username:"ravi"},{$inc:{count:1}}); // 第二次原子更新 await User.findOneAndUpdate({username:"ravi"},{$inc:{count:1}}); // 查看最终结果 const finalUser=await User.findOne({username:"ravi"}); console.log(finalUser); }
方案2:save前重新获取最新文档
如果必须使用save(),在修改前重新拉取数据库中的最新文档,确保本地文档版本与数据库一致:
async function helper(){ let user=await User.findOne({username:"ravi"}); console.log(user); // 第一次更新 await User.findOneAndUpdate({username:"ravi"},{$inc:{count:1}}); // 重新获取最新版本的文档 user=await User.findOne({username:"ravi"}); user.count+=1; const updatedUser=await user.save(); console.log(updatedUser); }
方案3:处理版本冲突并重试
捕获VersionError异常,在版本冲突时重新获取文档并重试更新:
async function helper(){ let user=await User.findOne({username:"ravi"}); console.log(user); await User.findOneAndUpdate({username:"ravi"},{$inc:{count:1}}); user.count+=1; try { const updatedUser=await user.save(); console.log(updatedUser); } catch (err) { if (err.name === 'VersionError') { // 版本冲突,重新获取文档后重试 const freshUser=await User.findOne({username:"ravi"}); freshUser.count+=1; const updatedUser=await freshUser.save(); console.log(updatedUser); } else { throw err; } } }
内容的提问来源于stack exchange,提问作者Ravi Sadam
相关产品推荐
相关产品推荐

