分库分表解决了什么问题?什么情况下需要分库分表?
1、应对海量数据单台MySQL数据库磁盘内存不足,数据表的数据量巨大,sql查询出现频繁磁盘io导致查询性能急剧下减
2、高并发单台数据库访问压力大,单台服务器cpu处理能力有限,cpu性能下降
如果出现以上情况那么就需要考虑MySQL数据库的分库分表操作
一、分库分表的维度
关于分库分表一般从两个维度:垂直和水平。具体怎么分还是得根据公司的具体业务情况分析
1、垂直拆分
垂直方向分结构,一般按业务模块 或字段属性进行纵向切割
垂直分库:将不同的业务表拆分到不同的数据库实例中,
例如 :将单库拆分为 user_db(用户库)、order_db(订单库)、product_db(商品库)。每个数据库实例存储一种业务的数据表
垂直分表:将一张表中不常用的字段或大文本字段(如 TEXT、BLOB)拆分到扩展表中。(同一数据库)
例如: user_base(存储 id, username, password,高频读取)与 user_detail(存储 id, bio, address, introduction,低频读取)
2、水平拆分
水平方向分数据,保持表结构不变,将数据行按照某种算法分散存储到多个库或多张表中
水平分库: 数据表结构一致,且分散在不同的数据库实例中的多张表中(如 db_0.order_0 到 db_3.order_15)。
水平分表: 数据表结构完全一致,数据分散在同一个库的 order_00、order_01、order_02 ... 中。
二、如何实现水平分库
关于水平分库一般采用一些路由算法(分片算法),我已经总结好在下面:
| 算法 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 哈希取模 | hash(key) % N |
分布均匀,实现简单 | 扩容需迁移大量数据 |
| 范围分片 | 按 ID/时间区间 | 范围查询高效,便于归档 | 易产生热点 |
| 一致性哈希 | 哈希环 + 虚拟节点 | 扩容迁移少 | 实现复杂,分布略不均 |
| 枚举分片 | 按枚举值映射 | 精确控制,适合地域/类型 | 需维护映射,易倾斜 |
| 日期分片 | 按年/月/日 | 适合时间序列,便于归档 | 新数据热点 |
| 复合分片 | 多字段组合 | 灵活 | 配置复杂 |
三、分库分表会带来哪些问题?
一般业务场景下能不引用中间件就不引用,因为引入某个中间件必定会带来一些问题,比如常见的数据库中间件redis,redis虽好可以缓存数据缓解MySQL数据库压力,但同时也会带来数据不一致、缓存三兄弟(击穿、雪崩、穿透)等等问题。
回到这个分库分表这个技术,分库分表可以解决高并发的问题但同时带来很多问题:
1、全局唯一 ID 问题
由于分库的实现,不同数据库下如果采用单表自增主键(AUTO_INCREMENT)在多表中会产生重复 ID,所以必须使用分布式 ID 生成器。
解决:
-
雪花算法(Snowflake): 基于时间戳 + 机器码 + 序列号生成的 64 位趋势递增 Long 型 ID(最常用)。
-
Redis 递增 / Segment 步长模式(如美团 Leaf): 批量获取自增 ID 段。
-
注意避开 UUID: 为什么?因为UUID 是无序字符串,作为 B+ 树主键会导致严重的数据页频繁分裂和磁盘随机 I/O,极大降低写入性能。
2. 跨库 JOIN 问题
数据被切分到不同数据库实例后,原生的 JOIN 语句无法跨物理库执行。
解决:
-
应用层组装(多次查询): 先查出主表数据,提取关联 ID,再用
IN (...)到目标库查询后在代码中拼装。 -
字段冗余(空间换时间): 在经常需要查询的表中冗余常用字段(如在订单表中直接保存
seller_name,避免JOIN商家表)。 -
全局表/字典表: 对变动极少但高频读取的表,在每个分库中都完整复制一份。
四、实际落地
在实际落地时,不需要手写底层切分逻辑,通常采用成熟的数据库中间件:
1、ShardingSphere-JDBC(前身 Sharding-JDBC)
原理: 以 Jar 包形式嵌入应用,重写 JDBC 接口,在应用内完成 SQL 解析、改写与路由。
优缺点: 性能高(无额外网络 Hop),无单点瓶颈;但对多语言不友好(主要支持 Java)
2、Mycat
原理: 独立部署为 Proxy 服务,伪装成 MySQL 协议。应用像连接普通 MySQL 一样连接 Proxy。
优缺点: 对应用完全透明,支持任意语言;但多了一层网络传输开销,且 Proxy 自身需要做高可用集群。
| 中间件 | 模式 | 特点 |
|---|---|---|
| ShardingSphere-JDBC | 客户端 | 嵌入应用,性能好,Java 专用 |
| ShardingSphere-Proxy | 代理 | 独立部署,多语言支持 |
| MyCAT | 代理 | 国内流行,功能全面,更新较慢 |
| Vitess | 代理 | YouTube 开源,超大规模,复杂 |
| ProxySQL | 代理 | 轻量,专注读写分离,不支持分片 |