如何实现MySQL分库分表?

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

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 代理 轻量,专注读写分离,不支持分片
相关推荐
小马同学-19 分钟前
MySQL主从复制和读写分离
数据库·mysql
谢亮_vipxieliang20 分钟前
Spring 事务失效的常见场景
java·开发语言·数据库·spring boot
海绵宝宝转agent33 分钟前
MySql高频面试八股开源笔记总结
mysql·面试·开源
geovindu1 小时前
sql: JSON and XML Data Handling in SQL using sql server 2025
大数据·数据库·sqlserver·数据库开发·数据库架构
IT大白鼠2 小时前
图数据库系列 · 第 02 篇——架构拆解:原生图存储到因果集群
数据库·架构·nosql
hweiyu002 小时前
Redis命令:HTTL
redis·缓存
h_a_o777oah2 小时前
【树论】树链剖分:将树形结构转化为线性结构以处理树上路径问题(洛谷 P3384 附C++代码模板)
数据结构·算法·线段树·acm·树链剖分·树论·重链剖分
余槐i2 小时前
数据没回滚也不报错:@Transactional 自调用失效的 3 种复现与修复
spring boot·mysql·多线程·spring 事务
HEJOO92 小时前
指针的算术运算详解
java·数据结构·算法
Coder-magician2 小时前
《代码随想录》刷题打卡day47:并查集-part01
数据结构·算法·图论