如何实现MySQL分库分表?

分库分表解决了什么问题?什么情况下需要分库分表?

1、应对海量数据单台MySQL数据库磁盘内存不足,数据表的数据量巨大,sql查询出现频繁磁盘io导致查询性能急剧下减

2、高并发单台数据库访问压力大,单台服务器cpu处理能力有限,cpu性能下降

如果出现以上情况那么就需要考虑MySQL数据库的分库分表操作

一、分库分表的维度

关于分库分表一般从两个维度:垂直和水平。具体怎么分还是得根据公司的具体业务情况分析

1、垂直拆分

垂直方向分结构,一般按业务模块字段属性进行纵向切割

垂直分库:将不同的业务表拆分到不同的数据库实例中,

例如 :将单库拆分为 user_db(用户库)、order_db(订单库)、product_db(商品库)。每个数据库实例存储一种业务的数据表

垂直分表:将一张表中不常用的字段或大文本字段(如 TEXTBLOB)拆分到扩展表中。(同一数据库)

例如: user_base(存储 id, username, password,高频读取)与 user_detail(存储 id, bio, address, introduction,低频读取)

2、水平拆分

水平方向分数据,保持表结构不变,将数据行按照某种算法分散存储到多个库或多张表中

水平分库: 数据表结构一致,且分散在不同的数据库实例中的多张表中(如 db_0.order_0db_3.order_15)。

水平分表: 数据表结构完全一致,数据分散在同一个库的 order_00order_01order_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 代理 轻量,专注读写分离,不支持分片
相关推荐
爱和冰阔落1 小时前
【Linux】条件变量为什么必须配合互斥锁:从 pthread_cond_wait 到阻塞队列
linux·运维·c++·缓存·中间件·安卓
风哥2号1 小时前
数据库教程FGMT33‑MySQL主从复制项目实施与维护06(MySQL8.4/9.7 MGR组复制)
数据库·mysql
liangsheng_g2 小时前
Spring事务传播行为分派与挂起恢复源码实战
数据库·sql·spring
蓝速科技2 小时前
信创终端 POC 测试实战与选型避坑指南丨蓝速科技
运维·数据库·人工智能·科技·自然语言处理
wdfk_prog2 小时前
VMware Ubuntu 虚拟机从 124 GB 压缩到 33 GB
运维·缓存·docker·容器
风哥2号2 小时前
数据库教程FGMT29‑Linux平台MySQL5.7安装配置与管理入门
数据库
ysu_03142 小时前
08-二叉树遍历:四种方式详解
c语言·数据结构·算法·leetcode
杨云龙UP3 小时前
MySQL Host is blocked because of many connection errors 导致 JDBC 连接失败排查与解决
linux·运维·网络·数据库·sql·mysql·登录失败
Lyyaoo.3 小时前
【二分查找】【中等】搜索二维矩阵/排序数组的第一位和最后位置/搜索旋转排序数组/旋转排序数组中的最小值
java·数据结构·算法