分库分表后,怎么设计,可以降低数据迁移的难度?
结论:迁移难度在设计期就决定了,取决于三件事——分片键是否可变、分片空间是否预留、数据是否有全局 ID 或时间戳可用于追增量。落地用五阶段迁移:双写 → 全量加增量追平 → 数据校验 → 灰度切读 → 切写并下线旧库,每一阶段都要能一键回滚。
一、设计侧的五条规矩
| 设计决定 | 好处 | 反例 |
|---|---|---|
| 分片键不可变 | 数据一辈子不因业务变更而搬库 | 用手机号分片,换绑就要迁移 |
| 预留分片空间(1024) | 扩容只搬表,不改算法 | 按 4 库写死,扩容必须重算 |
| 全局 ID 加时间戳 | 增量同步可断点续传 | 只有自增主键,无法判断新旧 |
| 逻辑表名抽象 | 迁移只改路由配置 | 表名硬编码在 SQL 字符串里 |
| 双写开关 | 迁移期可随时回退 | 直接停服割接 |
二、五阶段迁移
①双写 ②全量 + 增量 ③校验 ④切读 ⑤切写/下线
┌────────┐ ┌─────────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ 新老库 │ ──► │ DataX 全量 │──►│ 行数与金额│──►│ 灰度 1% │──►│ 旧库只读 │
│ 同时写 │ │ binlog 追平 │ │ 摘要比对 │ │ 5%→50% │ │ 最终下线 │
└────────┘ └─────────────┘ └──────────┘ └──────────┘ └──────────┘
└──────────── 任一阶段异常,关掉双写开关即回滚 ────────────┘
每阶段停留多久取决于数据量与业务容忍度:全量同步按 10 MB/s 估算,一亿行大约 4 到 8 小时;binlog 追平后再做校验,校验通过才允许切读。
三、双写与开关
@Component
public class OrderWriter {
private final OrderMapper newMapper;
private final LegacyOrderMapper oldMapper;
private final SwitchService switches; // 配置中心下发
public void save(Order order) {
newMapper.insert(order); // 新库为主链路
if (switches.isOn("order.dual.write")) {
try {
oldMapper.insert(order); // 旧库旁路写
} catch (Exception e) {
log.warn("旧库双写失败 orderId={}", order.getId(), e);
metrics.counter("dual.write.fail").increment();
}
}
}
}
关键点:旧库写入失败绝不能影响主流程;缺口靠 binlog 补偿与校验任务修复,而不是靠重试把请求拖死。
四、校验 SQL
-- 按天比对行数与金额,差异超阈值即告警
SELECT DATE(create_time) AS d,
COUNT(*) AS cnt,
SUM(amount) AS amt
FROM t_order
WHERE create_time >= '2025-11-01' AND create_time < '2025-11-04'
GROUP BY DATE(create_time);
-- 更严格的摘要比对:主键集合与关键字段做 CRC32
SELECT COUNT(*) AS cnt,
SUM(CRC32(CONCAT_WS('#', id, user_id, amount))) AS digest
FROM t_order
WHERE create_time >= '2025-11-01' AND create_time < '2025-11-02';
新旧库各执行一次,cnt 与 digest 都相等才算通过;不等时按主键二分定位差异行。
五、常见追问
Q1:迁移期间的数据一致性怎么保证? 靠「全量快照 + binlog 增量」追平,再用校验任务发现差异并反查补偿。不要指望双写 100% 成功,网络抖动与超时必然留下缺口。
Q2:怎么回滚? 旧库保持可写、双写开关可关、路由配置可切回,三个条件同时满足才叫可回滚。切写完成后旧库至少保留一个业务周期的只读数据。
Q3:停机迁移可以吗? 数据量小、有维护窗口时可以,但要评估停服成本。互联网业务通常不接受,只能在线迁移。
Q4:历史冷数据也要迁吗? 不必。按时间归档到冷存储或对象存储,只迁活跃数据,迁移量能降一个数量级。
小结
- 迁移难度在设计期就决定了:键不可变、空间预留、有全局 ID 与时间戳。
- 五阶段迁移的核心是「双写 + 校验 + 灰度」,每一步都可回滚。
- 校验要有量化指标(行数、金额摘要),不能只靠肉眼抽查。