LOGO 首页 OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 技术文档 其他文档  
 
网站管理员

亿级表分库分表:实操步骤、最佳实践与注意事项

admin
2026年10月21日 0:48 本文热度 98

单表过亿,不是神话,是很多业务迟早会撞上的墙。DDL 锁表动辄几十分钟,备份恢复按天计,索引再建不起,大查询把从库拖垮——这时候再谈「加机器、加索引」往往只是止痛。真正的手术是分库分表:把一张巨型表拆成可运维的物理单元。

这篇不讲空概念,直接按生产实操写:什么时候该拆、分片键怎么选、架构怎么摆、迁移怎么灰度、哪些坑一次踩够。坐稳,开拆。

先泼冷水:分库分表是架构级改造,不是改个配置就能上线。跨片 JOIN、全局唯一、分布式事务、运维复杂度都会上来。能用分区表、归档、读写分离、ES/数仓扛查询的,先评估「不拆能不能活」。

什么时候该拆:信号比「行数」更重要

行数过亿是参考,不是硬门槛。更该看这些信号是否同时出现:

  • 写入吞吐顶满:

    单库磁盘 IOPS、binlog、锁竞争成为常态瓶颈,垂直扩容性价比越来越差。
  • 变更与备份不可接受:

    加字段、加索引、备份恢复窗口长到业务扛不住。
  • 热点数据集中:

    最近 N 天数据占绝大部分访问,历史数据拖累缓冲池与索引。
  • 查询模式清晰:

    绝大多数请求能带上同一业务键(用户、租户、订单号),适合路由。

若主要痛点是「复杂报表 / 多维分析」,优先把分析流量切到数仓或搜索引擎,别把 OLTP 表硬拆成「能搜但不能联表」的一堆碎片。分库分表解决的是在线交易规模,不是 BI。

整体架构:应用 → 路由中间件 → 多库多表

常见落地形态:业务仍写「逻辑表」名,由 ShardingSphere / 自研路由层 / Proxy 按分片键算到物理库表。库内再拆多张表,避免单表过大;库与库之间分散连接、磁盘与备份压力。

只分表不分库:适合单机磁盘与连接还够、主要是单表过大。实现简单,但主机天花板还在。分库又分表:适合写入与存储都顶满。成本与运维复杂度显著上升,规划时一次性把容量余量留足,避免半年后再二次拆。

分片键与策略:选错一次,全局返工

分片键是命根子。好的分片键满足三条:高频查询几乎都带它、基数够大且分布均匀、业务上尽量不变更。用户域常用 user_id,租户 SaaS 常用 tenant_id(注意大租户热点),订单流水常用 order_id 或「用户 + 时间」组合。

  • 取模(hash % N):

    均匀性好,扩容改 N 代价大,常配合一致性哈希或预留分片容量。
  • 范围(range):

    按时间/ID 段拆,利于归档与冷热分离,但易形成热点写在最新分片。
  • 目录表 / 映射表:

    灵活,但多一次查找,要防目录本身成为单点。

实操建议:先按「未来 2~3 年峰值」估算分片数,一次到位或按 2 的幂预留,少做「先 8 张再 32 张」的二次迁移。单表目标可按业务定:例如单表行数千万级、数据文件几十~一两百 GB 内,DDL 与备份仍可控。

ShardingSphere JDBC 风格的最小配置示例(逻辑示意,库表名按环境改):

# application.yml(节选)
spring:
  shardingsphere:
    datasource:
      names: ds0,ds1
      ds0:
        jdbc-url: jdbc:mysql://db0:3306/order_db
      ds1:
        jdbc-url: jdbc:mysql://db1:3306/order_db
    rules:
      sharding:
        tables:
          t_order:
            actual-data-nodes: ds$->{0..1}.t_order_$->{0..7}
            table-strategy:
              standard:
                sharding-column: user_id
                sharding-algorithm-name: order-table-mod
            database-strategy:
              standard:
                sharding-column: user_id
                sharding-algorithm-name: order-db-mod

路由算法可简化理解为:

db_index  = user_id % 2
table_index = (user_id / 2) % 8
# 或统一:hash(user_id) % (2 * 8) 再映射到库表

实操步骤:按这个顺序走,少开事故会

  1. 评估与选型:

    梳理 TOP 查询与写入路径,确认分片键覆盖率;定只分表还是分库分表;选中间件还是应用内路由;定目标分片数与容量模型。
  2. 定策略与约束:

    写出「禁止跨片 JOIN」「禁止无分片键全表扫」「全局 ID 方案」「分页只能带分片键或走 ES」等红线,先改业务代码再迁数据。
  3. 建新库表与索引:

    物理表结构与单表对齐;索引只保留必要二级索引,避免每张表都拷贝一套臃肿索引。
  4. 双写 / 灰度写入:

    新流量双写旧表+新分片,或按用户尾号灰度;旧数据用离线任务按分片键灌入。
  5. 全量 + 增量迁移与校验:

    全量批导 + binlog/Canal 增量追平;按主键抽样 + 全量 count/checksum 对账;差异清单可重放。
  6. 切读再切写:

    先按比例切读到分片,观察延迟与错误;再切主写;保留快速回滚开关(读回旧表)。
  7. 观察与下线旧表:

    稳定一个窗口后停双写、归档旧表;文档与监控看板同步更新。

迁移任务伪代码节奏(生产必须限流、可断点续跑):

# 按主键区间扫描旧表,写入对应分片
last_id = 0
batch = 1000
while True:
  rows = SELECT * FROM t_order
        WHERE id > :last_id ORDER BY id LIMIT :batch
  if not rows: break
  for row in rows:
    route = shard(row.user_id)
    INSERT INTO route.db.route.table ... ON DUPLICATE KEY UPDATE ...
  last_id = rows[-1].id
  sleep(throttle_ms)  # 保护在线库

校验至少做两层:行数对齐(按分片键聚合对比)与字段抽样/哈希(关键列 MD5)。只比 count 不够,漏写、错路由、半更新都会被 count 骗过。

全局 ID、事务与查询:拆完之后的三座大山

全局唯一 ID:别再依赖单库自增。常见方案:号段模式(Leaf)、Snowflake 类、UUID(存储与索引更差)、或「分片号 + 本地序列」。订单号最好自带路由信息(或可反解出 user_id),否则客服查单、对账会哭。

事务:同库同片尽量本地事务;跨片用最终一致(本地消息表、Outbox、可靠消息)优先于强一致 XA。下单扣库存这类,优先通过业务设计把关键写收敛到同一分片键。

查询:带分片键的点查/列表是舒适区;后台「按手机号查全部订单」要么倒排索引表,要么同步到 ES。跨片分页用 limit/offset 会放大成各片深翻页,优先游标或业务禁止深翻。

最佳实践清单(可直接贴进技术方案)

  • 先改访问模式,再迁数据:

    代码里消灭「无分片键查询」,否则中间件只能广播,拆了更慢。
  • 容量一次留足:

    分片数按增长预估,减少二次 Re-sharding。
  • 双写要有开关与对账:

    写失败策略写清楚(主成功从失败如何补偿)。
  • 迁移可断点、可限流:

    高峰降速,低峰加速;进度落库。
  • 监控按物理表建:

    连接数、慢 SQL、复制延迟、分片倾斜(行数/体积 TopN)。
  • 大租户单独治理:

    SaaS 场景给超大租户独立库/独立分片,避免 hash 均匀掩盖业务不均匀。
  • 历史数据归档:

    冷数据迁历史库或对象存储 + 索引,在线分片只留热数据。

注意事项与踩坑:每一条都值钱

坑 1:分片键选了会变的字段。用户换绑、订单改归属,路由漂移导致数据找不到或重复。分片键应近似不可变。

坑 2:以为中间件能透明兼容所有 SQL。跨库 JOIN、子查询、部分聚合、事务边界都会踩雷。上线前用真实 SQL 清单做兼容性测试。

坑 3:只迁数据不改分页/报表。管理后台一查全站订单,广播到所有分片,CPU 集体起飞。后台查询要单独产品方案。

坑 4:双写不一致无对账。切流当天才发现从库少单。对账任务要在灰度期每天跑,差异可回放。

坑 5:扩容用「取模改 N」硬切。大量数据要搬家。提前预分片,或采用一致性哈希 / 扩容工具链,并把扩容演练写进预案。

坑 6:忽略连接池与配置翻倍。10 个库 × 每库连接池,应用侧连接打满数据库。maxPoolSize 要按物理源重算,不是照搬单库配置。

坑 7:DDL 在所有分片上手搓。缺一张表、少一个索引就会局部故障。用变更平台批量执行,并做结构一致性巡检。

什么时候可以不拆:更便宜的选项

  • 分区表(Partition):

    仍在单实例内,利于归档删除,不解决单机写上限。
  • 冷热分离 / 归档:

    在线表只留近 N 个月,历史进冷库。
  • 读写分离 + SQL 治理:

    读多写少且单机写仍健康时,往往更划算。
  • 垂直拆分:

    大字段、低频列拆到扩展表,先减单表宽度再谈水平拆。

能垂直拆、能归档、能把分析打出去,就别急着上水平分片。分库分表是「买扩展性」,同时「卖」简单性。

结语

亿级表分库分表,可以收成一条作战链:先确认值得拆 → 选对分片键与容量 → 改访问模式 → 双写迁移对账 → 切读切写可回滚 → 监控与归档常态化。技术细节可以换成不同中间件,但这条顺序别跳。

下次评审有人只说「表太大了,分 64 张」,你可以追问三句:分片键是什么?无分片键查询怎么处理?切流怎么回滚?答得清,方案才算站得住。

全文完。


阅读原文:原文链接


该文章在 2026/10/21 12:28:51 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2026 ClickSun All Rights Reserved  粤ICP备13012886号-2  粤公网安备44030602007207号