
Mgo 库本身不缓存 mgo.Dial() 传入的连接字符串,也不会复用旧数据库名;问题通常源于代码中对 session.DB("old-db-name") 的显式调用未同步更新,导致实际操作仍指向已删除的旧库。
mgo 库本身不缓存 `mgo.dial()` 传入的连接字符串,也不会复用旧数据库名;问题通常源于代码中对 `session.db("old-db-name")` 的显式调用未同步更新,导致实际操作仍指向已删除的旧库。
在使用 mgo(v2)连接 MongoDB 时,一个常见误解是:只要更新了 mgo.Dial() 中的完整连接 URL(含新数据库名),整个应用就会自动切换到新库。但事实并非如此——mgo.Dial() 仅负责建立与 MongoDB 服务器的网络连接,并不决定后续操作的具体数据库上下文。
真正指定数据库名称的位置,往往出现在获取 session 后调用 .DB("db-name") 的地方。例如:
session, err := mgo.Dial("mongodb://user:pass@dogen.mongohq.com:10048/new-db-name")
if err != nil {
log.Fatal(err)
}
defer session.Close()
// ⚠️ 关键点:此处显式指定了数据库名
db := session.DB("my-old-db-name") // ← 即使 Dial URL 已更新,这里仍用旧名!
c := db.C("users")
err = c.Find(nil).All(&results) // 报错:not authorized for query on my-old-db-name如上所示,尽管 Dial() 中的 URL 已指向 new-db-name,但 session.DB("my-old-db-name") 会创建一个独立于连接字符串中默认库名的数据库会话对象。MongoDB 认证和权限是按数据库粒度控制的,若新用户未被授权访问 my-old-db-name,就会触发你遇到的 not authorized 错误。
✅ 正确做法是确保所有 session.DB(...) 调用中的数据库名与目标库一致,并与连接字符串中的认证上下文匹配:
// ✅ 推荐:统一使用新数据库名
db := session.DB("new-db-name") // 与 Dial URL 中的库名或实际部署库名保持一致
c := db.C("users")? 额外注意事项:
- mgo 不缓存连接字符串,也不解析或保留 URL 中的数据库名作为默认值;它仅用该 URL 建立 TCP 连接并完成初始认证(认证凭据需对目标库有效)。
- 若 Compose.io 实例启用了「数据库级认证」(即用户绑定到特定 DB),则必须确保:
- 用户在新数据库中已创建并授予权限;
- 所有 session.DB(...) 调用、集合操作、索引管理等均指向该新库。
- 使用 go install 无法解决此问题,因为这不是编译缓存问题,而是运行时逻辑错误。
? 调试建议:
- 全局搜索代码中所有 session.DB(,确认参数是否已更新;
- 检查用户权限:登录 MongoDB Shell,执行 db.getUser("your-user"),验证 roles 是否包含对新库的读写权限;
- (可选)启用 mgo 日志:设置 session.SetSafe(&mgo.Safe{W: 1}) 并捕获更详细的错误上下文。
总之,mgo 的行为完全符合预期——它忠实执行你写的每一行代码。所谓“连接旧库”,实则是你的业务逻辑仍在主动请求旧库,而非框架缓存所致。










