当一张表数据量达到 2亿条 以上时,即使有主从库,也可能遇到以下问题:

  • 查询变慢,索引树过大,点查延迟明显。
  • 批量写入、归档效率低。
  • 表结构变更(DDL)风险高。

这时,就需要考虑 水平拆分(分库/分表)。本文结合一个“点查为主”的业务场景,介绍如何安全、平滑地完成大表拆分。

1. 拆分思路

1.1 为什么拆分

  • 减少单表数据量,提升查询和维护效率。
  • 提高系统扩展性,支持未来数据继续增长。

1.2 拆分方式

  1. 水平分表:在同一个库里创建多张表,把数据均匀切开。

    • 优点:运维简单,迁移快。
    • 缺点:数据库单点压力仍然存在。
  2. 水平分库 + 分表:把数据拆到多个库里,每个库再分多张表。

    • 优点:扩展性最强,单库压力小。
    • 缺点:改造成本高,涉及分布式事务和路由。

如果只是单库,先做水平分表即可。

2. 拆分方案设计

假设有一张订单表 order,2亿条数据,查询条件以 订单号点查 为主:

2.1 分片键选择

  • 订单ID(order_id):自增或雪花算法生成,能均匀分布。
  • 取模方式:例如 order_id % 16 → 把数据拆到 16 张表。

2.2 新表设计

1
2
3
4
order_00
order_01
...
order_15

与原表结构完全一致。

2.3 路由规则

  • 写入:按 order_id % 16 选择目标表。
  • 查询:由代码或中间件(如 ShardingSphere、MyCat)根据 ID 定位表。

3. 数据迁移流程

为了保证 生产安全,迁移必须采用 灰度切流 + 双写 + 校验 的方式:

步骤 1:准备环境

  • 创建分表 order_00order_15
  • 配置好代码里的路由逻辑(支持新老表双写)。

步骤 2:灰度切流

  • 先让一部分新写入(比如 1% 用户)走新表,其他仍然写老表。
  • 验证新表能正常查询、写入。

步骤 3:历史数据迁移

  • 使用迁移脚本(推荐 批量+限速 的方式):

    1
    2
    3
    4
    5
    INSERT INTO order_03 (col1, col2, ...)
    SELECT col1, col2, ...
    FROM order
    WHERE order_id % 16 = 3
    LIMIT 10000;

    配合任务调度器分批跑,避免锁表。

步骤 4:双写校验

  • 迁移期间,写操作同时写入老表和新表。

  • 定期做 数据校验

    • 行数比对:

      1
      2
      SELECT COUNT(*) FROM order WHERE order_id % 16 = 3;
      SELECT COUNT(*) FROM order_03;
    • 校验哈希:对比 MD5/SUM 聚合。

步骤 5:全量切换

  • 确认迁移完成、校验通过后,关闭老表写入。
  • 所有请求统一走新表。

步骤 6:回收老表

  • 观察一段时间后,老表只保留归档数据,或直接下线。

4. 风险与安全保障

  1. 不影响生产

    • 迁移分批次+限流,避免一次性锁全表。
    • 业务代码支持双写,保证数据一致。
  2. 回滚预案

    • 灰度期间若新表有问题,立即回切老表。
    • 保证老表在迁移前始终可用。
  3. 监控报警

    • 校验迁移速率、落库延迟。
    • 重点监控主从延迟和慢查询。

5. 总结

  • 拆分本质:减少单表压力,提升扩展性。
  • 点查业务:适合用主键取模分表。
  • 迁移原则:灰度切流 → 双写迁移 → 数据校验 → 全量切换。
  • 生产保障:限速迁移、校验数据、保留回滚预案。

一句话记忆:
“小步快跑,双写保命,先灰度再全量”


© 2024 竹林听雨 使用 Stellar 创建
总访问 113 次 | 本页访问 26