MySQL 分库分表 / ShardingSphere 内核 005 — SHARDING

MySQL 分库分表
ShardingSphere
内核剖析 与 实践。

当 MySQL 单表数据量达到千万级别后,索引维护、查询性能持续下滑,单库硬件扩容也存在上限。Apache ShardingSphere 作为开源分布式数据库中间件,完整提供分库分表、读写分离、分布式事务、数据加密能力,对应用近乎透明。本文深度拆解其核心引擎:SQL 解析、路由、改写、执行、归并。

单表瓶颈
1000万+
内核引擎
5STAGES
产品形态
2MODES
侵入性
低
CHAPTER 01
01/06

五大内核引擎 全流程拆解

SQL 解析 → 路由 → 改写 → 执行 → 归并。一条原始 SQL 从应用层进入,经过五个引擎流水线处理,最终返回归并后的统一结果集。这是 ShardingSphere 的核心心脏。

CORE PIPELINE — 五大引擎数据流
SQL 解析 → 路由 → 改写 → 执行 → 归并
STAGE 01 SQL 解析 PARSER STAGE 02 SQL 路由 ROUTER STAGE 03 SQL 改写 REWRITER STAGE 04 SQL 执行 EXECUTOR STAGE 05 结果归并 MERGER RAW SQL MERGED RESULT
01 / PARSER
SQL 解析引擎
IN: SQL 文本
OUT: AST 语法树
02 / ROUTER
路由引擎
IN: 分片条件
OUT: 目标分片
03 / REWRITER
SQL 改写引擎
IN: 逻辑表名
OUT: 物理表名
04 / EXECUTOR
SQL 执行引擎
IN: 物理 SQL
OUT: 多分片结果
05 / MERGER
结果归并引擎
IN: 多路数据流
OUT: 统一结果集
STAGE 01 / PARSER
SQL 解析引擎

这是整个框架的入口模块。使用 ANTLR4 语法库构建 MySQL 标准语法解析器,将原始 SQL 文本解析为抽象语法树 AST,提取表名、查询字段、分片键、查询条件、聚合函数、排序信息。

  1. 使用 ANTLR4 语法库,构建 MySQL 标准语法解析器;
  2. 将原始 SQL 文本解析为抽象语法树 AST;
  3. 提取表名、查询字段、分片键、查询条件、聚合函数、排序信息。
⚠ PAIN POINT 复杂子查询、多表关联、特殊函数会大幅提升解析难度;非法 SQL 会直接拦截。
STAGE 02 / ROUTER
路由引擎

基于解析出的分片条件,结合分片算法,定位 SQL 需要下发到哪些库、哪些表。两种路由模式:精准路由与广播路由。

精准路由 PRECISE
OPTIMAL
命中少量分片
SQL 携带分片键等值条件,只命中少量分片,性能最优。
SQL DB_0 DB_1 DB_2 DB_3 RESULT
广播路由 BROADCAST
FULL SCAN
全分片扫描
不带分片键,需要向所有分片库表下发 SQL,性能差,业务尽量规避。
SQL DB_0 DB_1 DB_2 DB_3 MERGE
SHARDING ALGORITHM
主流分片算法
01 / HASH
哈希分片
user_id % N
均匀打散数据,适合无热点的均匀分布场景。扩容时数据迁移量大。
02 / RANGE
范围分片
[start, end)
按时间 ID 区间分片,适合时序数据。易产生热点分片(最新数据集中)。
03 / COMPOSITE
复合分片
f(k1, k2, ...)
多字段联合分片,适合复杂业务路由规则。实现复杂度高。
⚠ CLASSIC TRAP 分片键缺失导致全分片查询,数据库连接数暴涨、查询超时。这是分库分表方案最常见的事故源。
STAGE 03 / REWRITER
SQL 改写引擎

原始 SQL 中的逻辑表名(t_order),需要改写为真实物理表名(t_order_0、t_order_1)。同时处理分页参数修正、别名统一、字段补全等逻辑。

原始 SQL — 逻辑表名
-- 应用层发出的 SQL SELECT * FROM t_order WHERE user_id = 1001;
→
改写后 SQL — 物理表名
-- 路由命中分片0,改写后下发 SELECT * FROM t_order_0 WHERE user_id = 1001;
STAGE 04 / EXECUTOR
SQL 执行引擎

支持多数据源并行执行 SQL,基于线程池调度;提供连接池管理、超时控制、失败重试,兼容多种数据库连接池(HikariCP、Druid 等)。

STAGE 05 / MERGER
结果归并引擎

多个分片返回独立数据集,中间件统一合并结果。三种归并类型:

01 / PAGINATION
分页归并
多分片 limit 数据合并后重新分页。
shard_0: [0:5]
shard_1: [0:5]
→ merge → [5:10]
02 / SORT
排序归并
多路有序数据流归并排序。
shard_0: [1,3,5]
shard_1: [2,4,6]
→ merge → [1,2,3,4,5,6]
03 / AGGREGATION
聚合归并
sum/count/max 等函数二次聚合计算。
shard_0: count=120
shard_1: count=80
→ merge → count=200
⚠ PERFORMANCE DISASTER 分页 limit offset, size 在全分片场景极易出现性能灾难——每个分片都要扫描 offset+size 条记录。大数据场景建议使用游标分页替代偏移分页。
CHAPTER 02
02/06

分库分表 前后拓扑对比

从单库单表 1000 万+ 数据爆满,到多库多表分散存储与查询压力。下方为两种方案的数据库拓扑结构对比。

BEFORE / 单库单表
单表 1000 万+ 数据爆满
索引膨胀 · 查询下滑 · 扩容触顶
DB_INSTANCE t_order 1000万+ ROWS ⚠ BOTTLENECK SINGLE POINT
1 DB
1 TABLE
10M+ ROWS
AFTER / 多库多表
分散至 4 库 × 2 表
存储分散 · 连接充足 · 查询并行
DB_0 t_0 t_1 DB_1 t_0 t_1 DB_2 t_0 t_1 DB_3 t_0 t_1 SHARDED ~125万/表
4 DB
8 TABLES
~1.25M ROWS/TABLE
3.2 / READ WRITE SPLIT
读写分离

自动区分读、写 SQL:DML 写操作路由至主库;SELECT 查询负载均衡分发至多个从库。支持主从延迟规避、强制走主库 Hint 语法。

01 / SHARDING
水平分表(同库多表)
单库内拆分多张表,解决单表数据量大问题。无法解决单库连接数、存储上限。
02 / SHARDING
水平分库分表(多库多表)
同时拆分数据库与数据表,兼顾连接数、存储、查询压力。生产环境主流方案。
CHAPTER 03
03/06

落地 常见问题与解决方案

四类高频工程痛点。分库分表不是银弹,落地前必须想清楚这些边界问题。

01
分布式主键
PAIN POINT 分表环境不能依赖数据库自增主键(多库主键冲突)。 SOLUTION 可选方案:雪花算法、UUID、ShardingSphere 内置 SNOWFLAKE 主键生成器。
02
跨分片 Join
PAIN POINT ShardingSphere 不支持跨库复杂关联查询。 SOLUTION 大表小表广播表;业务层 Join;冗余关联字段,避免跨分片关联。
03
分布式事务
PAIN POINT 跨分片 DML 操作无法依赖单库事务保证一致性。 SOLUTION ShardingSphere 支持:本地事务(单分片);XA 强一致性事务;Saga、TCC 最终一致性事务(适合长事务业务)。
04
分片扩容痛点
PAIN POINT 固定哈希分片扩容会导致大量数据迁移(user_id % N 中 N 变化,几乎所有数据要重新分片)。 SOLUTION 采用一致性哈希分片,或提前预留分片数量(如一开始就分 16/32 库,先只启用部分物理库)。
CHAPTER 04
04/06

选型对比 Sharding-JDBC vs Sharding-Proxy

ShardingSphere 包含两大产品形态。前者是客户端中间件,后者是独立代理服务。选型取决于技术栈与运维诉求。

方案 优势 劣势 适用场景
Sharding-JDBC 无额外服务、性能高 仅 Java 可用 Java 微服务项目
Sharding-Proxy 跨语言、统一管控 新增一层网络转发 多语言混合架构、DBA 统一运维
PRODUCT POSITIONING Sharding-JDBC:JDBC 驱动层,客户端中间件,无独立服务进程,性能损耗最低。
Sharding-Proxy:独立代理服务,数据库网关,支持多语言客户端,便于 DBA 统一运维。
SUMMARY
05/06

总结 透明化分片,但非银弹

ShardingSphere 通过中间件透明化分片逻辑,让业务代码几乎不需要感知多库多表。但分库分表属于架构侵入性方案,优先考虑业务分拆、冷热数据分离、索引优化,最后再选择分片。

01 / BEFORE SHARDING
分片前的优先选项
  • 业务分拆:按业务域拆分微服务与数据库
  • 冷热数据分离:历史数据归档至冷库
  • 索引优化:覆盖索引、联合索引、执行计划分析
  • 读写分离:主从架构先扛住读压力
02 / BEFORE GO-LIVE
分片实施前必须规划
  • 定义好分片键:选错即全分片扫描
  • 预估数据增长:至少预估 3 年容量
  • 规划扩容策略:一致性哈希或预留分片
  • 规避典型陷阱:全分片查询、跨分片 Join、偏移分页
结语 / EPILOGUE

分库分表是
最后的手段,
不是第一选择。

ShardingSphere 通过五大引擎流水线——解析、路由、改写、执行、归并——把分片逻辑透明化,让业务代码几乎不需要感知多库多表的存在。这是它在工程上最大的价值。

但请记住:分库分表是架构侵入性方案。一旦走上这条路,跨分片 Join、分布式事务、扩容迁移、偏移分页等问题会伴随整个系统的生命周期。优先考虑业务分拆、冷热分离、索引优化,把分库分表留到最后。

实施前必须定义好分片键、预估数据增长、规划扩容策略。否则,分片不是解药,而是下一个深坑。