sharding-jdbc分库分表无需停服,可通过升级从库+双写灰度实现热迁移;t_order与t_order_item须设为绑定表以避免笛卡尔积;4.0.0-rc1已过时,应升级至5.3.x;广播表需手动同步且仅适用低频配置数据。

Sharding-JDBC 分库分表到底要不要停服?
绝大多数业务扛不住停服迁移——不是技术做不到,而是线上订单、支付、库存等链路一断,分钟级就可能触发资损或客诉。ShardingSphere 本身不提供“自动热迁移”能力,但你可以用“升级从库 + 双写灰度”组合拳绕过停服。
- 先在从库上按新分片规则建好
t_order_0、t_order_1等物理表,保持主从同步不中断 - 应用层双写:老逻辑写原单库单表,新逻辑按
order_id % 4写到四个分片;通过开关控制灰度比例 - 数据一致性靠校验脚本兜底,比如对比
select count(*) FROM t_order WHERE order_id % 4 = 0和对应分片表行数 - 切完流量后,旧表只读、逐步归档,避免长期双写拖慢写入性能
为什么 t_order 和 t_order_item 必须设为绑定表?
因为跨分片 JOIN 不是 sql 被拒绝那么简单——ShardingSphere 会把 JOIN t_order_item 拆成 N×M 条独立查询,再做笛卡尔积合并,内存爆掉、超时、OOM 都是常态。绑定表本质是告诉框架:“这两张表的分片键一致,路由一定落在同一节点”。
- 配置里必须显式声明
spring.shardingsphere.rules.sharding.binding-tables[0]=t_order,t_order_item - 分片键要严格对齐:比如
t_order.order_id和t_order_item.order_id都参与分片,且用相同算法(不能一个取模、一个按时间范围) - 一旦没配绑定表,又写了
JOIN,日志里会出现Cannot support Cartesian product join报错,但不会直接抛异常,容易漏测
sharding-jdbc-spring-boot-starter-4.0.0-RC1 还能用吗?
不能直接用于新项目。这个版本发布于 2022 年初,已停止维护,且存在明确兼容性雷区:
- 不支持 mysql 8.0+ 的
caching_sha2_password认证插件,连不上新版 MySQL - 与 spring boot 2.6+ 的 Jakarta EE 命名空间冲突,启动报
javax.validation类找不到 - 分布式事务仅支持 XA(Atomikos),不支持 Seata 的 AT 模式,而 AT 是当前主流
- 建议升到
shardingsphere-jdbc-core-spring-boot-starter5.3.x 或更高,配置项前缀也从spring.shardingsphere变成了spring.shardingsphere.props
广播表 t_config 改动后,怎么保证所有分片库实时生效?
广播表不是“自动同步”,而是每次执行 INSERT/UPDATE/delete 时,ShardingSphere 主动把语句发给所有数据源。所以它只适合低频变更、高读取的配置类数据。
- 不要在
t_config上加唯一索引或外键,否则多库并发写可能触发主键冲突或锁等待 - 如果用了 Druid 连接池,记得关掉
useGlobalDataSourceStat=false,否则广播操作会被统计成 N 次独立调用,监控毛刺严重 - 最易忽略的一点:广播表不参与分片路由计算,但如果你在 SQL 里写了
WHERE config_id = ?,ShardingSphere 仍会尝试解析该条件——虽然最终不影响执行,但会多一次无意义的解析开销
分库分表真正难的从来不是配置写对,而是业务 SQL 是否天然适配分片模型。一个 GROUP BY create_time 加个 LIMIT 20,背后可能是 8 个库并行查再归并排序,稍不注意就拖垮整个连接池。