Go多数据库分库分表核心是为每个物理库单独sql.Open()并管理连接池,驱动必须编译期注册且全部预导入;GORM v2需显式传Dialector;ShardingSphere-Proxy需适配逻辑库名与分片键SQL;分片逻辑须业务层手写。

Go 项目里配置多数据库分库分表,核心不是“选哪个驱动”,而是**必须为每个物理库单独 sql.Open()、单独管理连接池、且驱动注册必须在编译期完成**。不存在“一个驱动支持分库分表”的说法,database/sql 本身只面向单实例。
驱动注册必须写死在 main 包里,运行时无法动态加载
Go 的 database/sql 驱动靠 init() 函数注册,这个动作发生在编译阶段。如果你的配置里写了 driver: "postgres",但代码里没写 _ "github.com/lib/pq",运行时就会 panic:sql: unknown driver "postgres" (forgotten import?)。
- 所有可能用到的驱动(
mysql、postgres、sqlite3)都得提前 blank-import 到main.go或会被编译进二进制的包中 - 哪怕你只部署 MySQL,也建议把
postgres驱动一起 import —— 它不会增加运行时开销,只是让二进制稍大一点 - 别尝试用
plugin或反射动态加载驱动,Go 官方不支持,且sql.Register()不是导出函数
每个物理库必须调用一次 sql.Open(),不能共用连接池
*sql.DB 是为单数据源设计的:连接复用、事务绑定、超时控制都基于单一地址。强行把多个 DSN 塞进同一个 sql.Open(),结果不是连不上,就是事务只作用于第一个成功连接的库。
- 例如有 4 个分片库
shop_0~shop_3,就得初始化 4 个独立的*sql.DB实例 - 每个实例都要单独调
SetMaxOpenConns()和SetMaxIdleConns();热点分片(比如shop_0)连接数要设高些,冷分片可设低 - 不要用全局变量直接暴露
*sql.DB,推荐封装成带名称的 struct,比如type ShardDB struct { Name string; DB *sql.DB }
GORM v2 多数据源必须传 Dialector,不能只靠配置字符串
GORM v2 不再接受 gorm.Open("mysql", dsn) 这种写法,它要求显式传入驱动对应的 Dialector 实例。这意味着你不能仅靠 YAML 里的 driver: "mysql" 就自动匹配。
立即学习“go语言免费学习笔记(深入)”;
- MySQL 场景下要写
gorm.Open(mysql.Open(dsn), &gorm.Config{}),其中mysql是github.com/go-gorm/mysql包 - PostgreSQL 对应
postgres.Open(dsn),来自github.com/go-gorm/postgres - 如果混用多种数据库,就得在初始化逻辑里根据配置
switch driver,分别调不同驱动的Open()函数 - 别指望
gorm.Model(&User{})自动路由到不同库——它只认当前传入的*gorm.DB实例,分库逻辑得你自己写在 DAO 层
ShardingSphere-Proxy 不需要 Go 端配驱动,但必须改连接地址和 SQL 写法
Proxy 是独立 Java 进程,Go 应用只需把它当普通 MySQL 连,用标准 go-sql-driver/mysql 即可。但连接参数和 SQL 有硬性约束,否则会绕过路由或报错。
- DSN 中的
database参数填逻辑库名(如shop),不是物理库名(如shop_0) - SQL 必须显式含分片键值,例如
WHERE user_id = 12345;用WHERE user_id = ?在某些 Proxy 版本下会路由失败 - 禁止出现物理表名,比如
SELECT * FROM t_order_3—— 这会直接报错Table 'db.t_order_3' doesn't exist - 事务默认是单库本地事务;想开 XA 得在 Proxy 配
transaction_type: XA,但多数 Go MySQL 驱动不支持该协议,实际不可用
真正麻烦的从来不是驱动怎么配,而是分片键选哪个、表名怎么拼、ID 怎么生成、跨分片查询怎么合并——这些全得在业务代码里手写,没有框架能替你做决定。



















