Go项目无法直接集成ShardingSphere,必须通过ShardingSphere-Proxy代理(连localhost:3307),所有分片规则配置于Proxy的config-sharding.yaml中,Go层仅发含显式分片键值的标准SQL。

Go 项目里所谓“使用 Sharding 框架”基本等于选错方向——ShardingSphere 不是 Go 的框架,它跑在 JVM 上;Go-Sharding 是可选但需独立部署的代理,不是你 import 就能用的库。
ShardingSphere-Proxy 是唯一现实可行的“Sharding 框架”接入方式
Go 应用无法直接调用 ShardingSphere 的分片逻辑,因为它是 Java 进程。你只能把它当 MySQL 代理连:localhost:3307(默认 Proxy 端口),而不是真实数据库的 :3306。所有分片规则必须写在 Proxy 的 config-sharding.yaml 里,Go 层只发标准 SQL。
- 连接字符串中的
database参数填逻辑库名(如shop),不是物理库名(如shop_0) - SQL 中必须显式包含分片键值,例如
WHERE user_id = 12345;用WHERE user_id = ?可能因驱动或 Proxy 版本导致路由失败 - 禁止写死物理表名,比如
SELECT * FROM orders_202405—— 这会绕过 Proxy,报错Table 'db.orders_202405' doesn't exist - 事务默认是单库本地事务;开启 XA 需 Proxy 配置
transaction_type: XA,但多数 Go MySQL 驱动不支持 XA 协议,实际不可用
Go-Sharding 要求你像运维一样启动和配置
Go-Sharding 是 Go 写的代理,不是 SDK。它用 TiDB SQL Parser 解析语句,支持 inline 表达式(如 t_order_${user_id % 8}),但你得自己编译、部署、维护这个服务进程。
- 配置文件放在
etc/目录下,示例见example/namespace/;不能嵌入 Go 项目代码中 - 启动命令类似
./go-sharding -config=etc/config.yaml,监听端口后,Go 应用连它即可 - 它不提供 Go 客户端包,
import "github.com/xxx/go-sharding"是无效操作 - 日志用
uber/zap,调试时要看它的 stdout 或日志文件,不是你的 Go 服务日志
别指望 ORM 自动分库分表:gorm、gdb、sqlx 都不干这事
无论你用 gorm、GoFrame gdb 还是 sqlx,它们都只面向单个 *sql.DB 实例。所谓“集成 ShardingSphere”,只是换了个数据库地址——底层仍是普通驱动通信,ORM 对分片完全无感。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
立即学习“go语言免费学习笔记(深入)”;
-
g.DB().Model("t_order")中的"t_order"是逻辑表名,必须与 Proxy 配置的actualDataNodes: ds_0.t_order_${0..7}匹配 - 如果你用
gdb.Table("t_order_3")强制指定物理表名,就跳过了分片逻辑,查不到数据或写错库 - 跨分片
JOIN、ORDER BY、GROUP BY在 Proxy 层可能被拒绝或结果错误,得在 Go 层手动合并 - 分页要特别小心:
LIMIT 20 OFFSET 1000在多分片上执行后,需 Go 层归并再截断,否则漏数据
自研路由比套框架更可控,但代价明确
如果业务规则简单(如固定按 user_id % 4 分库、order_id % 8 分表),自己封装 ShardedDB 比强塞 Proxy 更轻量、更易调试。
- 每个物理库单独调用
gorm.Open,存进[]*gorm.DB切片,GetDB(userID)函数返回对应实例 - 表名拼接必须业务强绑定:
"orders_" + time.Now().Format("200601")或"orders_" + strconv.Itoa(int(userID%8)) - 主键必须用
sony/flake这类分布式 ID,禁用自增;且注意时钟回拨——flake.NextID()默认 panic,得捕获降级 - 跨库更新必须放弃事务,改用本地消息表 + 重试,或者 TCC 模式;别写
tx, _ := db.Begin()后切不同库
真正容易被忽略的点是:分片键一旦选定就极难变更。比如用 user_id 分库,后续想按 region 拆分读流量,就得在 Go 层做二次路由,而不是靠某个“框架自动支持”。分库分表从来不是加个依赖就能跑的事,它是数据访问层的契约,写进 DAO,刻进日志,也埋在每一次 WHERE 条件里。

















