MySQL分库分表方案实战:从拆分策略到数据迁移

单表数据量过亿、单库连接数打满,是MySQL数据库分库分表最典型的触发信号。分库分表解决的是容量和并发问题,但引入的复杂度不小。本文从拆分时机、分片键选择、中间件选型到存量数据迁移,给出完整落地路径。

什么时候该分库分表

先别急着拆,按两个指标判断:

容量维度:单表数据超过500万-1000万,或表容量逼近2TB,B+树层级变深,写入和查询明显变慢。
并发维度:单库连接数长期接近上限,或热点表写入锁竞争严重。

如果只是读压力大,优先上缓存(Redis)和读写分离,分库分表放在最后考虑。拆完的数据多副本、跨库查询、分布式ID、事务问题都会冒出来,复杂度是几何级上升的。

垂直拆分与水平拆分

垂直拆分按业务域拆表:把用户表、订单表、商品表分到不同库,顺带把字段拆成主表+扩展表,解决行宽问题。水平拆分把同一张表的数据按规则分到多库多表,容量翻倍。常见做法:

# 示例:订单表按 user_id 取模分16库,每库16表(共256表)
分库: order_db_{0..15}  路由键 user_id % 16
分表: order_{0..15}     路由键 user_id / 16 % 16

分片键(sharding key)必须从业务访问模式里选,通常用最频繁的等值查询字段:用户体系用user_id,订单体系用order_id。选错分片键会导致大量跨库查询,性能反而更差。

分库分表中间件选型

ShardingSphere-JDBC:应用内嵌入式,性能最好,适合新项目直接集成。
ShardingSphere-Proxy:独立代理,兼容性强,适合已有系统平滑改造。
MyCat:老牌代理,支持多语言客户端,功能偏传统。

新系统建议ShardingSphere-JDBC(代码级控制),存量系统改造用Proxy降低侵入。分片配置示例(Java):

# sharding.yaml 订单库分片配置
rules:
  - !SHARDING
    tables:
      order:
        actualDataNodes: order_db_${0..15}.order_${0..15}
        tableStrategy:
          standard:
            shardingColumn: user_id
            shardingAlgorithmName: mod16
    defaultDatabaseStrategy:
      standard:
        shardingColumn: user_id
        shardingAlgorithmName: mod16

分页与跨库查询的处理

分库分表后,不带分片键的查询需要广播到全部分片再聚合,业务要设计降级路径:

1. 强制业务查询带分片键(user_id),走单分片。
2. 不带分片键的列表页走ES(Elasticsearch)或宽表副本。
3. 跨分片排序,中间件合并后内存排序,数据量大时提前limit。

最忌讳的就是”全表扫分片+内存聚合”,并发一上来直接打爆库。

存量数据迁移:双写+影子表

存量数据迁移是分库分表里风险最高的步骤,推荐”全量+增量+双写校验”方案:

1. 目标库建好分片表(影子表)。
2. 用DataX、canal等工具全量同步历史数据。
3. 业务双写:写新库的同时在影子表同步一份,开启binlog订阅校验。
4. 校验通过后切换读流量,再切写流量。
5. 保留旧库一段时间的只读,灰度回滚。

# 示例:canal监听binlog同步增量
canal.instance.master.address=127.0.0.1:3306
canal.instance.filter.regex=orderdb\\.order_.*

迁移期间用影子表对比每一条数据的MD5或版本号,确保两端一致再切流。

分库分表后的数据一致性

跨库跨表的事务,老方案靠分布式事务(XA/Seata),新方案尽量拆事务。维护成本从”拆表”转向”拆业务”,把一次性大事务拆成多个最终一致的小步骤。同时建立分片监控:各分片的数据分布、热点分片、慢SQL,第一时间发现倾斜问题。

分库分表只是手段,不是目的。数据量大先归档冷数据,读压力大先上缓存和读写分离,把这些做干净再评估要不要动库,投入产出比高得多。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/mysql-fen-ku-fen-biao-fang-an-shi-zhan-cong-chai-fen-ce/

(0)
小编小编
上一篇 3小时前
下一篇 3小时前

相关推荐