MySQL

MySQL 分片系统设计

·10 分钟阅读·3752 字

整理 MySQL 分片系统设计 的核心概念、关键流程与实践要点

📋 目录

MySQL 分片系统设计

  1. 分片架构完整流程

  2. SQL 路由原理

  3. ShardingSphere 内部工作机制

  4. 分片键设计方法

  5. 分片生产故障案例

  6. 云数据库平台如何治理分片


1. 一个真实的 MySQL 分片架构

先看大型系统通常是什么样子。

                 用户请求
                    |
                    |
              业务服务
                    |
                    |
          -------------------
          |                 |
      SQL访问层        数据访问层
          |
          |
    ShardingSphere
          |
          |
 ------------------------------------------------
 |                     |                         |
订单分片库0          订单分片库1              订单分片库2
 |                     |                         |
mysql-master0      mysql-master1          mysql-master2
 |
slave             slave                  slave

这里有几个关键角色:

2. 业务服务

例如:

订单服务:

createOrder()
queryOrder()

它只知道:

select * from orders

不知道数据在哪。


3. ShardingSphere

它负责:

  • SQL解析

  • 判断目标库

  • SQL改写

  • SQL执行

  • 结果合并

它实际上充当:

数据库访问代理层


4. SQL路由到底怎么实现?

这是分片最核心的地方。

假设:

有4个数据库:

order_db_0
order_db_1
order_db_2
order_db_3

规则:

database = user_id % 4

现在执行:

SELECT *
FROM orders
WHERE user_id=10001;

5. SQL解析

ShardingSphere解析SQL:

得到:

表:
orders

条件:

user_id = 10001

它知道:

user_id
是分片字段

6. 计算路由

执行:

10001 % 4

结果:

1

所以:

目标库:

order_db_1

7. SQL改写

原SQL:

SELECT *
FROM orders
WHERE user_id=10001

变成:

SELECT *
FROM order_db_1.orders
WHERE user_id=10001

8. 发送请求

连接:

mysql-01:3306

执行:

execute(sql)

9. 如果SQL没有分片键怎么办?

这是生产里面非常常见的问题。

例如:

SELECT *
FROM orders
WHERE create_time>'2026-01-01';

问题:

没有:

user_id

系统不知道:

数据在哪个库

怎么办?

10. 方案1:广播查询

发送:

db0

select...


db1

select...


db2

select...


db3

select...

然后:

合并结果。

流程:

          SQL

           |

     分片路由判断

           |

 ---------------------

 |        |           |

db0      db1         db2

 |        |           |

结果0   结果1       结果2

           |

       merge

           |

       返回用户

问题:

如果:

100个分片

一次查询:

100次SQL。

所以生产环境会限制这种查询。


11. 分片键设计为什么非常重要?

很多系统失败,不是因为技术不好,而是:

分片键选错。


假设订单表:

order_id
user_id
merchant_id
create_time

选择:

12. 方案A:

order_id

问题:

用户查询:

select *
from orders
where user_id=10001

无法定位。

只能:

扫描所有分片。


13. 方案B:

user_id

更合理。

因为:

用户订单天然聚集:

用户A

订单
支付
物流
评价

都可以定位。


但是也有问题:

超级用户:

例如:

user_id=888888

一天:

100万订单

那么:

固定分片:

db2

压力巨大。

这叫:

数据倾斜


14. 分片算法的发展

15. Hash分片

最简单:

user_id % N

优点:

简单。

缺点:

扩容困难。


例如:

4个库:

id %4

扩展:

8个库:

id %8

大量数据迁移。


16. 一致性哈希

思想:

把节点放到环上。

例如:

          DB0

      /        \

 DB3             DB1


          DB2

数据:

根据hash定位。

增加节点:

只影响附近数据。

例如:

增加:

DB4

只迁移:

DB3附近的数据

17. 虚拟分片

现在大型系统更常用。

例如:

不是:

4个数据库

而是:

1024个逻辑分片

例如:

user_id

 |

hash

 |

slot 0-1023

 |

映射

 |

真实数据库

结构:

slot

0-255
 |
db0


256-511
 |
db1


512-767
 |
db2


768-1023
 |
db3

扩容:

增加:

db4

只迁移部分slot。

这也是很多分布式系统思想。

例如:

  • Redis Cluster

  • Elasticsearch shard

  • Kafka partition

都有类似思想。


18. 分片和事务问题

这是很多面试不会讲,但生产很重要。

单库:

事务:

BEGIN;

insert order;

insert payment;

COMMIT;

一个MySQL完成。


分片后:

订单:

order_db_1

支付:

payment_db_2

怎么办?

变成:

事务跨两个数据库

叫:

分布式事务


传统方案:

19. XA事务

流程:

协调者

 |
 |
 ----------------

DB1 prepare

DB2 prepare


 |

commit

问题:

性能差。


互联网常用:

20. 最终一致性

例如:

订单:

创建订单

先写:

order_db

发送消息:

Kafka

消费者:

payment服务

更新支付。

架构:

订单服务

 |
 |
订单库

 |
消息队列

 |
支付服务

 |
支付库

21. 生产故障案例

22. 案例1:热点分片

背景:

电商活动。

分片:

user_id % 16

正常:

每个库:

CPU 40%

活动开始:

明星用户:

user_id=8888

产生:

50万订单

结果:

db8:

CPU 100%

IO 100%


其他:

30%

现象:

订单接口延迟增加

排查:

看:

QPS

慢SQL

CPU

磁盘IO

锁等待

发现:

单分片压力异常

解决:

短期:

限流。

长期:

改变分片策略。

例如:

从:

user_id

变成:

user_id + order_id

或者:

增加:

二级分片

23. 云数据库平台如何管理分片?

这个和你的工作方向更相关。

云平台不会人工看每个库。

一般有:

24. 资源监控

采集:

MySQL Exporter:

CPU

QPS

TPS

Buffer Pool

Slow Query

Lock Wait

Replication Delay

进入:

Prometheus

25. 自动诊断

例如规则:

if

CPU > 90%

and

持续10分钟

and

QPS增长


then

判断热点分片

26. 自动治理

可能动作:

26.1. 禁止新实例调度

类似你之前设计的:

数据库节点资源池。

例如:

node mysql-01

CPU 95%

禁止创建实例

26.2. 分片迁移

例如:

db2压力高

迁移slot 600-700

到db5

26.3. 自动扩容

例如:

order_db数量:

4

|

8

27. 对你的学习路线建议

结合你现在:

  • Kubernetes

  • Prometheus

  • Python自动化

  • 云数据库运维

  • AIOps方向

MySQL分片建议学习顺序:

第一阶段

MySQL主从复制
↓
Binlog
↓
读写分离


第二阶段

分库分表
↓
ShardingSphere
↓
分片算法


第三阶段

分布式事务
↓
消息最终一致性
↓
CAP理论


第四阶段

数据库智能运维

指标采集
↓
异常检测
↓
容量预测
↓
自动调度

你之前做的“根据 MySQL 节点指标决定是否允许创建实例”的思路,本质上已经接近云数据库资源调度系统,下一步可以继续深入:

“云数据库平台如何实现 MySQL 实例自动调度、容量预测和故障自愈(类似腾讯云数据库内部架构)”。 这个方向和 AIOps 结合会更贴近你的目标。


关联文档

Yanche Blog

记录云原生、Linux、数据库等技术领域的学习心得,以及日常生活的思考与感悟。

© 2026 Yanche Blog. All rights reserved.

Powered by Astro