C#调用updateOne()更新数据库文档出现延迟是什么原因
问题原因
你遇到的更新后短时间读不到新值的问题,基本逃不开以下三类原因:
- 异步方法未等待执行完成。绝大多数C# MongoDB驱动的仓储封装中,更新操作本质是异步IO方法,如果你的
UpdateOne内部调用的是异步API,却没有用await或者Wait()等待数据库返回写入结果,方法会在更新指令刚发出去、还没落地的时候就直接返回。此时立刻查询,数据库还没完成写入,自然拿到旧值,等100ms左右写入完成后查询就能拿到新值。 - 写关注配置为非应答模式。如果你的数据库连接字符串或者MongoClient配置中写关注设置为
w:0,驱动发送完更新指令后不会等待数据库任何确认就直接返回,写入操作在数据库端还处于排队处理阶段,立刻查询必然读不到新值。 - 副本集架构下读从节点导致的同步延迟。如果你的数据库是副本集/分片集群部署,且读偏好配置为从节点读取,主节点写入的数据同步到从节点本身存在几毫秒到上百毫秒的延迟,写入后立刻读从节点就会拿到未同步的旧数据,等同步完成后查询才会返回新值。
现有代码的其他问题
你贴的业务代码还有两个明显问题:
- 内存中修改了
file对象的State和UpdateTime两个属性,但实际更新操作只给数据库的State字段赋值,UpdateTime字段完全没有更新,会出现内存数据和数据库数据不一致的问题。 Builders.Update.Set所在行缺少一个闭合括号,属于语法错误,实际运行前需要补全。
修复方案
- 所有异步数据库操作必须等待执行完成,不要使用发后不理的调用方式,同时补全缺失的字段更新逻辑:
// 异步方法标注async,返回值改为Task private async Task UpdateState(List<File> filesInfo, string state) { foreach(File file in filesInfo) { file.State = state; file.UpdateTime = DateTimeService.GetDateTime(); // 加await等待写入完成,同时补全UpdateTime字段的更新 await dbrepository.UpdateOneAsync( filter: i => i.Id.Equals(file.Id), update: Builders<File>.Update .Set(i => i.State, state) .Set(i => i.UpdateTime, file.UpdateTime) ); } }
- 检查数据库连接配置,将写关注调整为默认的
w:1(即主节点确认写入成功后驱动再返回),不要使用无确认的写入模式。 - 如果业务要求写入后立刻能读到最新数据,将读偏好调整为
Primary,所有读请求走主节点,彻底规避主从同步延迟带来的读旧问题;如果架构上必须读从节点,就只能接受毫秒级的同步延迟,或者针对刚写入的数据强制走主节点查询。
内容的提问来源于stack exchange,提问作者Jatin Kumar
相关产品推荐
相关产品推荐

