MongoDB默认Write Concern不生效,Go mgo驱动副本集读写操作报错
问题原因分析
- mgo v2驱动客户端配置优先级高于服务端默认配置:mgo初始化session时默认内置write concern为
w:1(仅主节点确认写入即可返回),只要客户端自带了write concern参数,服务端设置的默认write concern就不会生效。你手动调用SetSafe设置majority是显式覆盖了驱动默认的w:1,所以问题解决;删除后恢复驱动默认w:1,写入还没同步到多数节点就返回,后续读取自然拿不到数据。 - 服务端配置版本不兼容:
setDefaultRWConcern是MongoDB 4.4版本才新增的管理命令,如果你的副本集版本低于4.4,该命令执行后不会生效,服务端不会应用默认的majority写策略。 - 服务端配置未正确生效:你执行的
setDefaultRWConcern命令里重复传了writeConcern参数,该参数是命令本身的执行写策略,不是默认配置项,你可以执行db.adminCommand({getDefaultRWConcern: 1})验证默认配置是否确实存储成功。
解决方法
- 方案一:全局设置mgo session的write concern(最稳妥,兼容所有MongoDB版本)
在第一次初始化MongoDB连接获取全局根session时,直接调用SetSafe设置多数写入策略,所有后续通过Copy()/Clone()生成的子session都会自动继承该配置,不需要每次操作单独设置:
// 初始化全局session时设置 mongoSession, err := mgo.Dial("mongodb://replica1,replica2,replica3/?replicaSet=你的副本集名称") if err != nil { // 处理连接错误 } // 全局设置write concern为majority,所有子session继承 mongoSession.SetSafe(&mgo.Safe{ WMode: "majority", J: true, WTimeout: 5000, })
- 方案二:配置驱动使用服务端默认write concern
如果希望统一用服务端的默认配置,只需要在全局session初始化时将Safe设置为nil,客户端就不会携带默认的w:1参数,此时服务端的默认RW策略就会生效:
mongoSession.SetSafe(nil)
注意提前用getDefaultRWConcern命令确认服务端配置已正确存储,且MongoDB版本>=4.4。
- 方案三:配套调整读策略
如果你的应用读操作配置了从节点读取的偏好,建议同步将读策略设置为majority,避免主从同步延迟导致已提交的写入暂时无法从从节点读取到。
内容的提问来源于stack exchange,提问作者Amandeep kaur
相关产品推荐
相关产品推荐

