
mgo 库本身不缓存连接字符串,mgo.dial() 每次调用均以传入参数为准建立新连接;问题通常源于代码中后续通过 session.db("old-db-name") 显式指定了旧数据库名,而非连接字符串本身失效。
mgo 库本身不缓存连接字符串,mgo.dial() 每次调用均以传入参数为准建立新连接;问题通常源于代码中后续通过 session.db("old-db-name") 显式指定了旧数据库名,而非连接字符串本身失效。
在使用 mgo(v2)连接 MongoDB 时,一个常见误解是:修改 mgo.Dial() 的连接字符串后,应用仍访问旧数据库,便怀疑连接字符串被“缓存”。实际上,mgo 完全不会缓存或复用你传给 Dial() 的字符串——它仅解析该 URL 并据此初始化底层 TCP 连接与认证上下文。连接字符串中的数据库名(URL 路径部分,如 mongodb://u:p@h:port/my-old-db-name 中的 my-old-db-name)仅用于初始认证和默认数据库上下文,并不强制约束后续所有操作的目标库。
真正决定查询目标数据库的是你代码中显式调用的 session.DB("database-name")。例如:
session, err := mgo.Dial("mongodb://user:pass@dogen.mongohq.com:10048/new-db-name")
if err != nil {
log.Fatal(err)
}
// ❌ 错误:仍访问旧库(硬编码导致)
collection := session.DB("my-old-db-name").C("users")
// ✅ 正确:与连接字符串中声明的新库一致
collection := session.DB("new-db-name").C("users")⚠️ 注意:MongoDB 认证用户通常绑定到特定数据库(如 admin 或 my-old-db-name)。即使连接字符串指向 new-db-name,若用户权限仅授予 my-old-db-name,而你又调用 session.DB("my-old-db-name"),就会触发 not authorized for query on my-old-db-name —— 这并非连接失败,而是权限校验失败,恰恰证明连接已成功建立,且正在访问你指定的旧库。
排查建议:
- 全局搜索代码中所有 session.DB( 调用,确认数据库名是否已同步更新;
- 检查用户权限:登录 Compose.io 控制台,确认该用户名是否拥有对 new-db-name 的读写权限(必要时在 admin 库中创建对应角色);
- 避免硬编码:将数据库名提取为配置项(如 config.DatabaseName),统一管理;
- (可选)启用 mgo 日志辅助诊断:session.SetSafe(&mgo.Safe{W: 1}) 并捕获错误详情。
总之,mgo 的行为是确定且透明的:连接字符串不缓存,数据库路由由 session.DB() 动态决定。问题根源几乎总是代码中数据库名未同步更新,而非框架机制异常。










