MySQL 分库分表详细介绍
创作时间:
作者:
@小白创作中心
MySQL 分库分表详细介绍
引用
CSDN
1.
https://m.blog.csdn.net/weixin_45428910/article/details/145722600
随着业务数据量的增长,单库单表的数据库架构往往难以满足性能和容量的需求。本文将详细介绍MySQL分库分表的技术方案,包括分库分表的原因、方式、策略、实现方法以及数据一致性保证等多个方面,帮助读者掌握这一重要的数据库扩展技术。
一、为什么要分库分表?
当业务数据量增长到 单库单表 难以承载的程度时,会出现:
- 查询性能下降(索引树变大,查询变慢)。
- 写入性能瓶颈(锁冲突严重)。
- 存储容量受限(单表数据量超限)。
- 数据库单点故障风险。
解决方案
分库分表(Sharding)是一种 数据库水平扩展(Scale Out)方案,将数据拆分到多个数据库或数据表中,以提升系统吞吐能力和可扩展性。
二、分库分表的两种方式
1.分表(Sharding Table):
适用于单表数据量过大(如亿级别)。
数据拆分到多个表,仍然在 同一个数据库 中。
索引变小,查询性能提升。
2.分库分表(Sharding Database + Table):
适用于单库压力过大,主从同步瓶颈。
数据拆分到多个数据库和表,解决存储和并发问题。
适合分布式架构(但事务处理变复杂)。
三、分库分表的常见策略
1. 取模(HASH 取模)
- 方案:
数据库数:N
表数:M
分片算法:
库编号 = hash(主键) % N
表编号 = hash(主键) % M
- 示例(假设 4 库 8 表):
用户 ID 12345
数据库 = 12345 % 4 = 1
表 = 12345 % 8 = 5
数据落入 db_1.user_5 - 优点:
数据分布均匀,查询性能稳定。 - 缺点:
扩容困难,如 N=4,扩展到 8,数据需要 重新分配(导致数据迁移复杂)。
2. 范围(RANGE 分片)
- 方案:
按时间、ID 号段拆分:
用户ID 1-1,000,000 → db_1
用户ID 1,000,001-2,000,000 → db_2
- 示例(按时间分表,每月一个表):
CREATE TABLE orders_202401 (...);
CREATE TABLE orders_202402 (...);
- 优点:
数据分布直观,易管理。
支持按时间清理历史数据(如定期归档旧表)。 - 缺点:
热点数据集中(如最新数据查询压力大)。
不同表数据量不均衡(老表访问少,新表访问多)。
3. 按业务分库(垂直拆分 Vertical Sharding)
方案:
不同业务拆分到不同数据库,如:
用户数据 → user_db
订单数据 → order_db
日志数据 → log_db
- 优点:
业务隔离,减少互相影响。
单表数据量小,性能更稳定。 - 缺点:
跨库 JOIN 受限,需要 应用层聚合 。
某些库压力仍然可能过大(如订单库)。
4. 一致性哈希(Consistent Hashing)
方案:
采用 一致性哈希环,动态增加/删除节点时 减少数据迁移。
常用于 分布式缓存+数据库 组合架构。
示例(4 个库,新增第 5 个库时,仅部分数据重新分配):
- 原始:
hash(数据) -> db_1, db_2, db_3, db_4 - 新增 db_5:
仅 db_4 需要迁移部分数据到 db_5 - 优点:
动态扩容友好,数据迁移量小。 - 缺点:
实现较复杂,通常结合 一致性哈希中间件(如 Redis、ES)。
四、如何实现分库分表
1. 手动分库分表(应用层控制)
示例(Java 代码实现 Hash 分库分表)
public class ShardingUtil {
private static final int DB_COUNT = 4;
private static final int TABLE_COUNT = 8;
public static String getDatabase(String userId) {
int dbIndex = userId.hashCode() % DB_COUNT;
return "db_" + dbIndex;
}
public static String getTable(String userId) {
int tableIndex = userId.hashCode() % TABLE_COUNT;
return "user_" + tableIndex;
}
public static void main(String[] args) {
String userId = "12345";
System.out.println("Database: " + getDatabase(userId));
System.out.println("Table: " + getTable(userId));
}
}
2. 使用 ShardingSphere 进行自动分库分表
ShardingSphere 是 Apache 开源的数据库分库分表中间件,支持 读写分离 + 分库分表。
ShardingSphere 配置示例
spring:
shardingsphere:
datasource:
names: db_0, db_1
db_0:
url: jdbc:mysql://localhost:3306/db_0
username: root
password: password
db_1:
url: jdbc:mysql://localhost:3306/db_1
username: root
password: password
rules:
sharding:
tables:
user:
actual-data-nodes: db_$->{0..1}.user_$->{0..3}
table-strategy:
standard:
sharding-column: id
sharding-algorithm-name: user-inline
sharding-algorithms:
user-inline:
type: INLINE
props:
algorithm-expression: user_$->{id % 4}
五、如何保证分库分表的数据一致性
1. 事务管理
- 分库后本地事务(Single DB Transaction) 仍然有效。
- 跨库事务(Distributed Transaction) 需要使用 XA 事务 或 TCC 事务补偿机制。
2. 分布式 ID
- 由于 AUTO_INCREMENT 无法跨库,需要使用 分布式 ID 生成器:
- UUID(唯一但查询效率低)
- 雪花算法(Snowflake)
- MySQL 自增 ID 方案(每库步长不同)
- Redis 生成唯一 ID
六、总结
选型建议
数据量 < 5000万:单库,索引优化+分区表。
5000万 ~ 5亿:单库分表(Hash 分表)。
5亿以上:分库分表+分布式架构。
这样可以 保证数据库可扩展性、查询性能、事务一致性。
热门推荐
养鸽必读:鸽子饮水管理四大要点
唐诗代表人物生平简介:杨炯,被后人称为“杨盈川”
赵今麦评论区沦陷,网友让她退出娱乐圈,《漂白》敬业营销遭反噬
牙克石 探索出一条生态资源有效转化为经济价值和民生福祉的绿色发展路径
空气开关跳闸是什么原因
奔驰汽车保养提示复位指南
白扁豆的性质和作用(探究白扁豆的热性和凉性)
固态电池最全线路图:2030年全球出货量将达614.1GWh
轮胎速度等级越高越安全
我国学者揭示间歇性禁食抑制毛囊再生机制
轻食对健康的好处:权威研究解读
汽油可以存放在塑料瓶中吗?
蒲公英什么季节开花?属于几月份开的花?
租赁期间换房东怎么签合同?这份指南请收好
抗击化疗耐药性与肿瘤复发!山东大学研究团队用 AI 构筑乳腺癌干细胞的有力防线
电动车 在网上买好吗?网上买和实体店买价格差多少同样的车子
门诊报销社会保险指南:让您轻松了解如何享受门诊保险待遇
银行的结构性存款产品风险控制措施的有效性?
薪酬管理制度方案怎么制定才能符合公司战略?
中国银行怎么买黄金?黄金投资全攻略
乳胶床垫甲醛问题及去除方法详解
对比网飞《三体》和国版《三体》,如何理智评价?
西汉演义:最强十大战将武力排行榜
项羽的武力:历史真实与后世渲染的辨析
如何通过钢印识别黄金真伪?
法院判令:物业不到位,可以不交或少交物业费(附:可以拒交或少交物业费的几种情况)
业主以物业服务不到位为由拒缴物业费,法院这样判
古佛再来之关帝伽蓝菩萨
伽蓝菩萨的来历:智慧之光的慈悲救赎
天顶星座射手座的内涵解析