
在 Go 中使用 database/sql 可通过省略 DSN 中的数据库名(如 "user:pass@/")直接连接 MySQL 实例,再通过 USE db 或带库名的全限定查询(如 SELECT * FROM db.table)动态访问多个数据库,实现单池多库复用。
在 go 中使用 database/sql 为 mysql 实例(而非具体数据库)建立统一连接池,是管理多数据库场景下的高效实践。核心在于:连接池本身不绑定任何数据库,只需在 dsn 中省略数据库名即可。
MySQL 的 DSN 格式通常为:user:password@tcp(host:port)/dbname?params。若要去除数据库上下文、仅连接到 MySQL 实例层面,只需将 /dbname 部分留空或设为 /,例如:
dsn := "root:password@tcp(127.0.0.1:3306)/"
db, err := sql.Open("mysql", dsn)
if err != nil {
log.Fatal("failed to open connection pool:", err)
}
defer db.Close() // 注意:Close() 关闭整个池,非单次连接
// 可选:验证连接有效性
if err := db.Ping(); err != nil {
log.Fatal("failed to ping instance:", err)
}此后,所有 SQL 操作均可通过两种方式指定目标数据库:
-
✅ 运行时切换库:在执行业务查询前,先执行
USE database_name(需确保该连接未被其他 goroutine 并发复用,否则有状态污染风险):_, err := db.Exec("USE my_db_1") if err != nil { ... } rows, _ := db.Query("SELECT * FROM users") -
✅ 全限定表名查询(推荐):完全避免连接状态依赖,更安全、更符合连接池设计原则:
rows, err := db.Query("SELECT id, name FROM my_db_1.users WHERE status = ?", "active") // 或跨库 JOIN(需权限支持) rows, err := db.Query("SELECT u.name, p.title FROM my_db_1.users u JOIN my_db_2.posts p ON u.id = p.user_id")
⚠️ 重要注意事项:
- 不建议为每个数据库单独维护一个
*sql.DB实例(如用 map[string]*sql.DB),除非有强隔离需求(如不同用户权限、独立连接参数)。这会浪费资源并增加管理复杂度。 -
sql.Open返回的是连接池句柄,不是单个连接;db.Query/db.Exec会自动从池中获取可用连接,执行完毕后归还,无需手动释放。 - 若使用 XORM,其底层仍基于
database/sql,因此同样适用上述 DSN 写法;初始化时传入无库名 DSN 即可:engine, err := xorm.NewEngine("mysql", "root:pass@tcp(localhost:3306)/")
综上,Go 中实现“单连接池访问多数据库”的关键在于 DSN 去库名 + 全限定 SQL,既简洁又符合连接池语义,是生产环境中推荐的标准做法。


















