真正可行的无缝迁移路径只有双写过渡或基于binlog的cdc同步;mysqldump因导入锁表、无法捕获增量变更,必然导致数据不一致,不满足无缝要求。

mysqldump 不足以支撑“无缝”迁移,真正可行的路径只有两条:**双写过渡**或**基于 binlog 的 CDC 同步**。其他方案(如纯逻辑导入、物理拷贝)必然伴随停机或数据断层,不符合“无缝”定义。
为什么不能直接用 mysqldump + 停机切换?
因为“无缝”意味着业务无感知、写入不中断、查询不降级。而 mysqldump 导出期间虽可用 --single-transaction 保证一致性,但导入过程会锁表、阻塞写入,且无法捕获导入窗口内的新增变更——哪怕只差 1 秒,数据就已不一致。实际生产中,只要写入 QPS > 50,这个窗口就不可控。
canal + 全量+增量同步的实际配置要点
这是目前落地最稳、侵入最小的方案,但配置细节决定成败:
- 全量阶段必须在
canal启动前完成,且导入时需禁用目标库的外键和唯一约束(否则分片后主键冲突或唯一索引报错) -
canal的destination配置要与 MySQL 的server_id严格区分,避免与现有从库冲突 - binlog 格式必须为
ROW,且binlog_row_image = FULL,否则 UPDATE/DELETE 事件丢失旧值,分片路由无法判断原记录归属 - 分片路由逻辑不能写死在
canaladapter 里,建议抽离为独立服务,便于灰度验证和热更新
双写方案里最容易被忽略的事务一致性陷阱
应用层双写看似简单,但以下三点常导致线上事故:
- 旧库写成功、新库写失败时,若仅靠重试而不记录失败日志,重试窗口内重复写入可能触发分片键冲突(例如同一
user_id被哈希到不同分片) - 未对
INSERT ... ON DUPLICATE KEY UPDATE做兼容处理,MySQL 的REPLACE INTO在分库分表中语义完全不同,极易覆盖非预期数据 - 双写中间件(如 ShardingSphere-JDBC)若未开启
xa_transaction_manager,跨库事务回滚会丢失,只能靠事后补偿,而补偿逻辑本身又依赖新库可用——形成单点依赖闭环
切流前必须验证的三个数据状态
切换不是改个连接地址就完事。上线前至少要确认:
- 新库的
SELECT COUNT(*)和旧库完全一致,且按分片键分组统计(例如GROUP BY user_id % 4)各分片数量均衡 - 关键业务表的最新 100 条写入记录(按
create_time DESC)在新旧库中字段值逐行比对,尤其注意TIMESTAMP、JSON类型是否自动转换失真 - 旧库 binlog position 和
canal消费位点严格对齐,且canalclient 端无堆积(msgId差值











