真正能落地的无缝拆分迁移只有双写过渡或基于binlog的CDC同步;mysqldump因锁表、窗口期变更丢失、位点无法锚定、主键冲突及类型转换等问题,无法满足业务无感知、写入不中断、查询不降级的“无缝”要求。

真正能落地的无缝拆分迁移,只有双写过渡或基于 binlog 的 CDC 同步两条路;mysqldump 导入过程锁表、无法捕获窗口期变更,哪怕只差 1 秒,新旧库就已不一致。
为什么 mysqldump + 停机切换不满足“无缝”
“无缝”意味着业务无感知、写入不中断、查询不降级。mysqldump --single-transaction 能保证导出一致性,但导入时:LOCK TABLES 或 DISABLE KEYS 会阻塞写入;更关键的是,从 dump 结束到导入完成之间产生的新增/更新/删除,完全丢失。实际生产中,只要源库写入 QPS > 50,这个窗口就不可控——你根本来不及追平。
- binlog position 在 dump 后无法精确锚定,
SHOW MASTER STATUS返回的位置不是 dump 快照对应的真实位点 - 目标库导入期间若开启唯一索引或外键约束,分片后主键冲突直接报错
Duplicate entry 'xxx' for key 'PRIMARY' - JSON、TIMESTAMP、ENUM 类型在不同 MySQL 版本间可能自动转换,导致字段值肉眼一致但二进制不等
Canal 全量+增量同步的关键配置项
这是目前侵入最小、落地最稳的方案,但几个参数配错就会丢 UPDATE/DELETE 事件或路由失败:
解析 MySQL 8.0 的 DDL 脚本,并将表结构导出为 Excel 格式。适用于用户需将 MySQL 的 `CREATE TABLE` 语句转换为结构化的 Excel 文件场景,导出内容包含字段名、数据类型、长度及精度等信息。支持多张表的批量处理,每张表对应 Excel 中的一个独立工作表。适用于数据库文档编写、数据字典生成及模式分析等任务。
-
binlog_format = ROW必须显式设置,且binlog_row_image = FULL——否则 Canal 解析不到before字段,无法判断原记录属于哪个分片 - 全量导入必须在 Canal 启动前完成,且目标库需临时禁用外键检查:
SET FOREIGN_KEY_CHECKS = 0和唯一约束:ALTER TABLE t DISABLE KEYS -
destination名称不能与 MySQL 已有server_id冲突,否则 Canal 会被误识别为从库,导致 binlog 被跳过 - 分片路由逻辑不要硬编码在
canal-adapter配置里,应抽离为独立服务(如 HTTP 接口),便于灰度验证和热更新分片规则
双写方案里最常踩的三个事务陷阱
应用层双写看似可控,但以下三点在线上几乎必然引发数据错乱:
- 旧库写成功、新库写失败时,仅靠重试而不落盘失败日志,会导致同一
user_id在重试窗口内被哈希到不同分片,触发Duplicate entry -
INSERT ... ON DUPLICATE KEY UPDATE在分库分表中语义失效:新库的“重复键”可能是其他分片的主键,覆盖非预期数据 - 若使用 ShardingSphere-JDBC 等中间件双写,未启用
xa_transaction_manager,跨库事务回滚会静默失败,补偿逻辑又依赖新库可用——形成死循环依赖
切流前必须人工核验的三个状态
改连接串不是切换,上线前必须确认:
-
SELECT COUNT(*)在新旧库完全一致,且按分片键分组统计(如GROUP BY user_id % 4)各分片数量均衡,避免某分片空载或超载 - 取每张核心表最新 100 条写入记录(按
create_time DESC),逐字段比对,尤其注意TIMESTAMP是否被自动转成 UTC、JSON字段是否缩进/排序不一致(影响 MD5 校验) - 用
pt-table-checksum对所有表跑一次校验,重点看chunk级别差异,而不是只信总行数——小概率出现“总数对、局部错”的隐性不一致
真正难的从来不是把数据搬过去,而是让分片键解析、类型转换、约束处理、位点对齐这些细节,在几十张表之间保持一致且可验证。任何想靠“一次配置、全局生效”的简化思路,都会在第三张表出错时崩塌。

















