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

使用mgo驱动连接MongoDB副本集时OP_GET_MORE报错求助

问题原因分析

这个错误的本质是旧驱动协议与MongoDB集群配置的冲突:

  • 你使用的mgo驱动属于较老的MongoDB驱动,它处理游标分页(比如聚合查询返回大量数据时的getMore操作)时,用的是MongoDB旧的OP_GET_MORE网络协议操作码。
  • 当你给集群设置了自定义默认写关注(w:"majority")后,MongoDB会要求所有游标相关的后续操作必须使用命令式的getMore命令,不允许用旧的OP_GET_MORE操作——因为旧操作无法传递自定义写关注的上下文,而集群默认写关注会绑定到游标上,触发校验失败。
  • 把默认写关注设为{}时,相当于用MongoDB原生默认写关注(w:1),这时MongoDB允许旧的OP_GET_MORE操作,错误也就消失了。

另外提一句:你连接代码里连续调用了两次SetMode,mgo.SecondaryPreferred会覆盖前面的mgo.Monotonic,这行是多余的,可以删掉。

解决方案

方案1:针对读操作会话重置写关注

聚合属于读操作,不需要继承会话的写关注配置。你可以在创建会话副本后,显式重置写关注为默认,避免读操作带上majority写关注:

sessionCopy := mongoSession.Copy()
defer sessionCopy.Close()
// 重置写关注为默认,解决游标操作的协议冲突
sessionCopy.SetSafe(nil)

getCollection := sessionCopy.DB(MerchantDb.Database).C(config.BookingsCollection)
// 后续聚合代码不变

方案2:升级到官方MongoDB Go驱动

mgo已经停止维护多年,官方的mongodb-go-driver完全支持MongoDB最新协议,会自动使用命令式的getMore操作,从根源上避免这类协议兼容问题。

方案3:调整写关注的配置方式

如果业务需要写操作默认使用majority写关注,不要在集群层面设置defaultWriteConcern,而是只在写操作的会话中显式设置写关注,读操作的会话不设置:

  • 集群层面恢复默认写关注:
db.adminCommand({ setDefaultRWConcern: 1, defaultReadConcern: { level : "majority" }, defaultWriteConcern: {} })
  • 在执行写操作的代码中,单独设置写关注:
// 写操作会话
writeSession := mongoSession.Copy()
defer writeSession.Close()
writeSession.SetSafe(&mgo.Safe{WMode: "majority"})
// 执行插入、更新等写操作

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 05:55:27