Skip to content

如何实现分库分表

上一篇主要解决的是“查询性能”问题,比如:

  • 索引优化
  • SQL 优化
  • 缓存优化

但随着业务继续增长,系统会进入另一个阶段:

数据库写入量开始成为瓶颈。

典型场景包括:

  • 订单量暴涨
  • 用户量持续增长
  • 日志/消息海量写入
  • 高频交易系统

此时,即使查询已经优化得很好,数据库仍然可能被写请求压垮。

因为:

单机数据库的写能力是有上限的。

一、数据库为什么会出现写入瓶颈

MySQL 本质上仍然是:

单机系统。

它最终会受到:

  • CPU
  • 内存
  • 磁盘 IO
  • 网络带宽

等物理资源限制。

尤其写操作比读操作更昂贵,因为写入涉及:

  • redo log
  • binlog
  • 磁盘刷盘
  • 锁竞争
  • 索引维护

因此:

随着写入量增加,数据库很容易出现:

  • TPS 上不去
  • 锁等待严重
  • IO 打满
  • 延迟升高

二、为什么主从复制解决不了写瓶颈

很多人想到:

“既然数据库压力大,那加从库不就行了?”

但主从复制只能解决:

“读压力”。

因为:

  • 主库负责写
  • 从库负责读

所以:

text
读请求:可以横向扩展
写请求:仍然集中在主库

最终:

主库仍然会成为整个系统瓶颈。

因此:

当写入量成为核心问题时,必须拆库。

三、什么是分库分表

分库分表的本质其实非常简单:

“把一份大数据拆散”。

原来:

text
一个库
一张表

现在变成:

text
多个库
多张表

这样可以:

  • 分散写入压力
  • 分散磁盘 IO
  • 分散锁竞争
  • 提高整体吞吐量

本质上:

用“多台机器”共同承担写入压力。


四、分表与分库的区别

1. 分表

即:

一张大表拆成多张小表。

例如:

原表:

text
order

拆成:

text
order_1
order_2
order_3

但这些表仍然在:

同一个数据库实例里。

分表主要解决:

(1)单表数据量过大

数据太大后:

  • 索引膨胀
  • 查询变慢
  • B+树层级增加

(2)热点写入问题

写压力可以分散到不同表。

但:

分表不能突破单机数据库性能极限。

因为:

  • IO 还是同一台机器
  • CPU 还是同一台机器

五、什么是分库

分库:

数据分散到不同数据库实例。

例如:

text
db_order_1
db_order_2
db_order_3

不同库:

  • 不同机器
  • 不同磁盘
  • 不同 CPU

因此:

真正实现了:

写能力横向扩展。

六、垂直拆分与水平拆分

1. 垂直拆分(按业务拆)

例如:

原系统:

text
user
order
product

都在一个库里。

现在拆成:

text
用户库
订单库
商品库

垂直拆分的核心思想:

“按业务边界拆”。

垂直拆分解决的问题:

(1)业务耦合

不同业务隔离。

(2)单库过大

降低复杂度。

(3)团队协作

不同团队维护不同数据库。

但:

垂直拆分并没有真正解决“单表数据量”问题。

例如:

订单表依然可能上亿。


七、水平拆分(真正解决高并发)

水平拆分:

“同一张表的数据拆散”。

例如:

订单表:

text
order_1
order_2
order_3
order_4

每张表只保存部分数据。

八、数据如何拆分

分片规则(Sharding Key)。

这是分库分表最核心的问题。

1. 按范围拆分

例如:

text
1~1000万 → 表1
1000万~2000万 → 表2

优点:

  • 范围查询方便

缺点:

  • 热点集中

例如: 最新订单永远写最后一个表。

容易形成热点。

2. Hash 拆分(最常见)

例如:

text
user_id % 4

决定写入哪张表。

优点:

  • 数据均匀
  • 写入均匀
  • 压力平衡

缺点:

  • 范围查询困难

九、为什么分库分表后性能会提升

因为原来:

text
所有写请求 → 一个库

现在:

text
写请求 → 多个库分担

例如:

4 个库:

理论上:

  • 写入能力提升 4 倍
  • IO 分散
  • 锁竞争减少

本质是:

把单机瓶颈变成集群能力。


十、分库分表带来的核心问题

分库分表不是银弹。

它解决扩展问题, 但会带来大量分布式复杂性。


十一、分布式 ID 问题

原来:

数据库自增主键即可。

分库后:

多个库都会生成:

text
1
2
3

会冲突。

因此必须引入:

全局唯一 ID。

常见方案:

  • UUID
  • Snowflake
  • 号段模式

十二、跨库查询问题

例如:

sql
SELECT * FROM order WHERE create_time > xxx

数据散落多个库后:

必须:

  • 查询多个库
  • 合并结果

复杂度和性能成本急剧上升。

十三、分页问题

例如:

sql
LIMIT 0,20

原来:

一个库即可完成。

现在:

多个库:

  • 分别查询
  • 排序
  • 聚合
  • 再分页

实现非常复杂。

十四、排序与聚合问题

例如:

sql
ORDER BY
GROUP BY
COUNT
SUM

都变复杂。

因为:

数据已经不在同一个节点。

必须:

  • 分库计算
  • 再汇总

十五、分布式事务问题

这是最核心的问题之一。

原来:

一个数据库事务即可。

分库后:

多个数据库无法直接使用本地事务。

因此:

必须接受:

“最终一致性”。

常见方案:

  • 消息队列
  • TCC
  • Saga
  • 补偿机制

十六、为什么互联网系统普遍接受最终一致性

高并发系统优先保证性能和可扩展性。

因此:

互联网系统通常:

放弃强一致性, 换取:

  • 高吞吐
  • 高可用
  • 高扩展

例如:

  • 订单先成功
  • 库存异步扣减

十七、分库分表的核心原则

1. 不要过早分库分表

因为: 复杂度会暴涨。

优先:

  • 索引优化
  • SQL 优化
  • 缓存
  • 主从复制

2. 优先垂直拆分

因为: 业务边界更自然。

3. 分片键最重要

它决定:

  • 数据是否均匀
  • 是否容易扩展
  • 查询性能如何

4. 尽量避免跨库操作

因为: 性能和复杂度都会大幅上升。

十八、分库分表的本质

分库分表本质上是通过“数据拆分”来突破单机数据库写入能力上限。

它的核心收益是:

  • 分散写流量
  • 分散 IO
  • 分散锁竞争

但代价是:

系统从“单机数据库问题”变成“分布式系统问题”。

复杂度会显著提高。

十九、一句话总结

分库分表是高并发系统突破单机数据库写入瓶颈的核心方案,其中垂直拆分解决业务复杂度问题,水平拆分解决数据量和写入压力问题,而真正困难的部分并不是“拆”,而是拆完之后如何处理分布式事务、跨库查询和数据一致性等复杂问题。

Released under the MIT License.