☰
附-02 · MySQL 分库分表与中间件 —— ShardingSphere / MyCat 分片策略实战
2026/10/30 6:49:51 网站建设 项目流程

附-02 · MySQL 分库分表与中间件 —— ShardingSphere / MyCat 分片策略实战

系列定位:《MySQL 数据库全栈运维实战系列》第 附-02 篇(番外),与《Oracle 数据库全栈运维实战系列(VMware 版)》同构对标。适用版本:MySQL 8.0(5.7 差异随文标注)。官方文档:Apache ShardingSphere 官方文档、MyCat 开源社区文档、MySQL 8.0 Reference Manual。


一、什么时候该分库分表

图 1

单表超过 2000 万行、单库 TPS 超过单机上限、或者业务按租户天然隔离时,才需要分库分表。分库分表是最后手段,不是银弹——它会带来分布式事务、跨分片 JOIN、扩容迁移、全局唯一 ID 一系列复杂度。能靠索引优化、读写分离、缓存解决的,先别分。

图 2

方案代表类比 Oracle
垂直拆分按业务拆库(订单库/用户库)Oracle Schema 分离
水平分库同一张表按分片键散到多个库Oracle 无原生等价,靠分区表
水平分表单库内分多张表Oracle 分区表 Partition
中间件ShardingSphere / MyCatOracle 无对应产品,属架构层

VMware 虚机环境注意事项:分片后的每个分片都是一台独立 MySQL 实例(或独立虚机),虚机数量线性增长。测试环境建议 2~3 个分片节点 + 1 个中间件节点,全部跑在 VMware 上。中间件节点(ShardingSphere-Proxy/MyCat)本身无状态,可双实例 + VIP 高可用。分片节点的磁盘要各自独立 VMDK,不要多个分片挤一块盘。


二、两大中间件对比

维度ShardingSphere-JDBCShardingSphere-ProxyMyCat(1.6/2.x)
形态JDBC 客户端库,嵌应用内独立代理服务独立代理服务
侵入性应用引 jar,改配置零侵入,改连接串零侵入
多语言仅 Java任意语言任意语言
性能最好(无网络跳转)中间多一跳中间多一跳
运维配置散在各应用集中管理集中管理
社区Apache 顶级项目,活跃同左1.6 停更,2.x 社区弱
推荐度Java 业务首选异构语言/统一运维首选老系统存量,新项目不建议

三、分片策略怎么选

图 3

图 4

策略适用优点缺点
取模 id mod N等值查询均匀数据均匀、热点均衡扩容要迁移大量数据
范围分片(按时间)订单/日志按天归档易归档、易冷热分离热点(最近月份写集中)
一致性哈希动态扩缩容扩容只迁相邻节点实现复杂、数据略不均
按枚举(省/市/租户)天然隔离的业务业务清晰可能数据倾斜

分片键选择三原则:

  1. 绝大多数 SQL 都带这个键(否则全分片广播,性能灾难)。
  2. 数据分布均匀(别拿性别、地区做取模分片键)。
  3. 尽量不更新(分片键改了要跨分片迁移行)。

四、ShardingSphere-JDBC 5.x 实战

4.1 Maven 依赖

<!-- pom.xml(解释:5.x 稳定版,spring-boot-starter 更省事) --> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>shardingsphere-jdbc-core</artifactId> <version>5.4.1</version> </dependency>

4.2 YAML 分片配置(t_order 按 user_id 取模分 4 片)

# sharding.yml(解释:4 个真实库 ds0~ds3,t_order 按 user_id 取模路由) dataSources: ds0: dataSourceClassName: com.zaxxer.hikari.HikariDataSource driverClassName: com.mysql.cj.jdbc.Driver jdbcUrl: jdbc:mysql://db-shard-0:3306/order_ds0?useSSL=false&serverTimezone=Asia/Shanghai username: shard password: shard_pwd ds1: dataSourceClassName: com.zaxxer.hikari.HikariDataSource driverClassName: com.mysql.cj.jdbc.Driver jdbcUrl: jdbc:mysql://db-shard-1:3306/order_ds1 username: shard password: shard_pwd ds2: dataSourceClassName: com.zaxxer.hikari.HikariDataSource driverClassName: com.mysql.cj.jdbc.Driver jdbcUrl: jdbc:mysql://db-shard-2:3306/order_ds2 username: shard password: shard_pwd ds3: dataSourceClassName: com.zaxxer.hikari.HikariDataSource driverClassName: com.mysql.cj.jdbc.Driver jdbcUrl: jdbc:mysql://db-shard-3:3306/order_ds3 username: shard password: shard_pwd rules: - !SHARDING tables: t_order: actualDataNodes: ds0..3.t_order_0..16 databaseStrategy: standard: shardingColumn: user_id shardingAlgorithmName: db_mod tableStrategy: standard: shardingColumn: order_id shardingAlgorithmName: table_mod keyGenerateStrategy: column: order_id keyGeneratorName: snowflake shardingAlgorithms: db_mod: type: MOD props: sharding-count: 4 table_mod: type: MOD props: sharding-count: 17 keyGenerators: snowflake: type: SNOWFLAKE
-- 业务侧无感知(解释:应用还是写 t_order,中间件自动路由) INSERT INTO t_order (user_id, order_id, amount) VALUES (1001, 20261009001, 99.5); -- ShardingSphere 自动算:user_id=1001 对 4 取余为 1 路由到 ds1;order_id 对 17 取余为 8 路由到 t_order_08 -- 实际落在 ds1.t_order_08

五、ShardingSphere-Proxy 实战(独立代理)

Proxy 跑在独立节点,应用把它当普通 MySQL 连。

# 下载启动(解释:5.x 发行包解压即用,默认 3307 端口) tar -zxvf apache-shardingsphere-5.4.1-shardingsphere-proxy-bin.tar.gz -C /opt/ cd /opt/apache-shardingsphere-proxy-bin/ # 配置 conf/server.yaml 和 conf/config-sharding.yaml(结构同 JDBC 版 YAML) ./bin/start.sh # 应用侧连 Proxy(解释:和连普通 MySQL 没区别) mysql -h proxy-node -P 3307 -u sharding -p

图 5


六、MyCat 1.6 配置(存量系统参考)

MyCat 1.6 的经典配置由 schema.xml 和 rule.xml 两部分组成。

6.1 schema.xml(逻辑表与数据节点)

<schema name="orders_db"> <table name="t_order" primaryKey="order_id" dataNode="dn1,dn2,dn3,dn4" rule="order-by-user-id"></table> </schema> <dataNode name="dn1" dataHost="host0" database="order_ds0"/> <dataNode name="dn2" dataHost="host1" database="order_ds1"/> <dataNode name="dn3" dataHost="host2" database="order_ds2"/> <dataNode name="dn4" dataHost="host3" database="order_ds3"/>

6.2 rule.xml(取模分片规则)

<tableRule name="order-by-user-id"> <rule> <columns>user_id</columns> <algorithm>mod-four</algorithm> </rule> </tableRule>

对应的分片算法定义在 rule.xml 的 function 段:name 为 mod-four,实现类是 MyCat 内置的取模函数 PartitionByMod(完整包路径 org.opencloudb.route.function.PartitionByMod),参数 count=4,即按 user_id 对 4 取余路由到 4 个数据节点。

注意:MyCat 1.6 已多年不维护,是 JDK 7/8 时代产物,新项目不建议选;存量维护可参考,新系统一律 ShardingSphere 5.x。


七、分库分表的四大坑

7.1 跨分片查询

不带分片键的 SQL 会广播到所有分片,性能差。

-- 带分片键:单分片路由,快 SELECT * FROM t_order WHERE user_id = 1001 AND order_id = 20261009001; -- 不带分片键:全分片广播,慢(解释:必须避免) SELECT * FROM t_order WHERE create_time >= '2026-10-01';

解决:这种分析类需求走 ES / 列式库 / 单独的报表库,不要在分片库上跑。

7.2 分布式事务

跨分片写订单 + 库存,本地事务保不住。

方案说明
最终一致(推荐)本地消息表 / Canal 订阅 binlog,业务层对账补偿
XA 强一致ShardingSphere 支持 XA,但性能差,少用
Seata AT微服务体系常用,和 ShardingSphere 可集成

7.3 全局唯一 ID

自增主键在分库后会冲突。

方案说明
Snowflake(雪花算法)ShardingSphere 内置,64bit:时间戳+workerId+序列号
号段模式每个分片段式取号,DB 存 max_id
UUID索引不友好,InnoDB 主键尽量别用

7.4 扩容数据迁移

4 片扩到 8 片,取模规则变了,要重新分布数据。

图 6

工具:ShardingSphere-Scaling、DataX、自研迁移脚本。扩容期间必须双写 + 灰度切流。


八、类比 Oracle 速查

MySQL 分库分表Oracle 对应差异
水平分表Oracle Partition(RANGE/LIST/HASH)Oracle 原生分区在单库内,MySQL 要中间件跨库
垂直拆库Schema/业务拆库类似
分布式 IDOracle SequenceMySQL 自增不能跨分片,要雪花/号段
跨分片 JOIN分区裁剪 + 本地 JOINMySQL 跨库 JOIN 要中间件归并,性能差
ShardingSphere无官方等价Oracle 靠分区 + RAC 扩展,原生能力更强

九、踩坑记录(实测汇总)

#坑现象解决
1分片键选错(性别)数据倾斜到 1~2 个分片重新选 user_id/order_id 均匀键
2SQL 不带分片键全分片广播,慢 100 倍业务规范强制带分片键
3用 UUID 当主键InnoDB 页分裂严重,写入慢用 Snowflake 有序 ID
4取模分片扩容N=4 扩 N=8 要迁一半数据一次规划够 / 一致性哈希 / 双写迁移
5跨分片分布式事务用 XA性能掉一半改最终一致 + 本地消息表
6MyCat 1.6 新项目社区停更,bug 无人修用 ShardingSphere 5.x
7Proxy 单点代理挂了全站断Proxy 双实例 + VIP/负载均衡
8Snowflake 时钟回拨发重复 IDworkerId 绑定 + 时钟回拨检测报错
9跨分片 ORDER BY LIMIT排序归并耗内存加索引 + 禁止跨深分页
10分片后没做数据迁移校验新老库数据不一致行数+checksum 双向校验后再切流

十、本文要点速记

  1. 分库分表是最后手段:先索引、读写分离、缓存,顶不住再分。
  2. 中间件选 ShardingSphere 5.x:Java 用 JDBC 嵌应用,异构用 Proxy;MyCat 只维护存量。
  3. 分片键三原则:多数 SQL 带它、数据均匀、不更新。
  4. 取模 vs 范围:等值查询取模均匀,时间归档范围易冷热分离。
  5. 四大坑提前规划:跨分片查询、分布式事务、全局 ID、扩容迁移。
  6. 扩容双写 + 校验:别直接切,灰度切流。

十一、参考资料(官方正式文档)

主题官方链接
Apache ShardingSphere 官方文档https://shardingsphere.apache.org/document/current/cn/overview/
ShardingSphere-JDBChttps://shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere-jdbc/
ShardingSphere-Proxyhttps://shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere-proxy/
ShardingSphere 分片策略https://shardingsphere.apache.org/document/current/cn/features/sharding/concept/
ShardingSphere-Scaling(数据迁移)https://shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere-scaling/
MyCat 开源社区https://github.com/MyCATApache/Mycat2
MySQL 8.0 Reference Manualhttps://dev.mysql.com/doc/refman/8.0/en/
Snowflake 主键生成https://shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere-jdbc/yaml-config/rules/key-generator/

本文章属于《MySQL 数据库全栈运维实战系列》番外篇。欢迎收藏、交流。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询