SQL sharding 技术与应用案例

1次阅读

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

SQL sharding 技术与应用案例

Sharding-JDBC 分库分表到底要不要停服?

绝大多数业务扛不住停服迁移——不是技术做不到,而是线上订单、支付、库存等链路一断,分钟级就可能触发资损或客诉。ShardingSphere 本身不提供“自动热迁移”能力,但你可以用“升级从库 + 双写灰度”组合拳绕过停服。

  • 先在从库上按新分片规则建好 t_order_0t_order_1 等物理表,保持主从同步不中断
  • 应用层双写:老逻辑写原单库单表,新逻辑按 order_id % 4 写到四个分片;通过开关控制灰度比例
  • 数据一致性靠校验脚本兜底,比如对比 select count(*) FROM t_order WHERE order_id % 4 = 0 和对应分片表行数
  • 切完流量后,旧表只读、逐步归档,避免长期双写拖慢写入性能

为什么 t_ordert_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_idt_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-starter 5.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 个库并行查再归并排序,稍不注意就拖垮整个连接池。

text=ZqhQzanResources