MySQL 多分库同步 TiDB 前,源端分片表结构不一致,应该如何低风险处理?

我们有一批 MySQL 5.7 生产分库,库名类似 shsc_wms_wgb、shsc_wms_wlz、shsc_wms_wxa 等,现在要同步/迁移到 TiDB。

TiDB 目标库的表结构最初是从 shsc_wms_wgb 复制出来的。但实际生产里,其他分库的同名表结构并不完全一致。迁移工具做 table structure / sharding consistency check 时会报错,例如:different column definition
shsc_wms_wlz.w_company.business_object varchar(50)
shsc_wms_wxa.w_company.business_object varchar(50) CHARACTER SET utf8

  1. 同字段长度不一致
    company_name varchar(100) vs varchar(50)

  2. 字符集/排序规则不一致
    varchar(50)
    varchar(50) CHARACTER SET utf8
    varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci

  3. 部分分库多字段或少字段
    upstream has more columns than downstream: weight, volume, loading_dock

  4. 有些字段在部分生产库比 wgb 更长
    所以不能简单把所有库刷成 wgb,否则可能缩短字段

我们已经把所有生产库的 SHOW CREATE TABLE 都导出来了。初步分析下来,如果按 wgb 做基线,TiDB 能对齐 wgb,但源端其他 MySQL 分库之间仍然不一致,迁移校验还是过不了。

现在纠结的是处理顺序和基线选择:

  1. 是否应该先把所有 MySQL 源端分库的同名表结构统一,再让 TiDB 跟随统一后的结构?
  2. 源端统一时,是否应该采用“安全超集”原则:字段长度取最大,只扩不缩;缺字段补齐;字符集统一;真实类型冲突人工确认?
  3. 对字符集/排序规则不一致,应该逐列 MODIFY COLUMN,还是表级 ALTER TABLE … CONVERT TO CHARACTER SET utf8mb4 COLLATE …?生产 MySQL 5.7 下哪个风险更可控?
  4. 对几百条 DDL,生产上有没有推荐的执行策略?比如按表分批、先小表后大表、用 gh-ost/pt-osc,还是只处理迁移校验报错的点?
  5. TiDB 目标库应该以 wgb 为准,还是以所有 MySQL 源库统一后的安全超集为准?

我们的目标是:尽量少改生产 MySQL,不丢数据,不缩字段,能让 MySQL 分库结构一致性校验通过,并顺利同步到 TiDB。

想请教这种 MySQL 多分库同步 TiDB 的场景,大家一般怎么定基线、怎么处理字符集和字段定义不一致?

现阶段情况是 字段不一致的都好刷。 主要就是字符集 不一致的问题。 因为生产有70多个库,刷的脚本实在是太多了。 不知道如何是好了。请大佬们指点一二。 :joy_cat:

迁移的时候,通常情况下,不会再改动前端了,对前端的修改对应用都是不可控的。
最大化tidb的结构,将数据同步至TiDB把。

mysql 里面是分库分表 由于历史原因 里面的表字符集不一致。导致 同步tidb时报错。无法同步。现阶段只能解决前端问题之后才能同步。

表结构的校验能取消么?校验数据就可以了。
MySQL端能统一是最好的,就看风险是否可控了。
DM进行同步的?

怎么取消?

没使用过,只是想法,风险可控,优先统一上游。


TiDB Data Migration 任务前置检查 | TiDB 社区版

这个,应该要先统一上游吧

选型要看具体场景。如果数据量在百TB以内、读多写少、对强一致性有要求,TiDB 挺合适。如果数据量级不大(单机够用)或业务逻辑复杂(存储过程、触发器多),MySQL 更省事。建议拿业务做 POC 测试对比。

要比较的话得看系统瓶颈在哪。MySQL 是单点写入瓶颈,TiDB 通过 Raft + Region 分片解决。但分布式一致性开销(多数派写入)在跨 AZ 部署时延迟会更明显。关键还是业务场景匹配。

MySQL 保留 utf8/utf8mb4 异构,TiDB 表统一 utf8mb4。 TiDB 完全兼容 MySQL utf8(三字节)数据,读取 / 写入不会乱码

配置 ignore-checking-items跳过分库结构校验,TiDB 表建成超集结构(最长字段、最全字段、utf8mb4 字符集),不改动 MySQL,快速解决同步报错。

  • 基线选择:不能以 shsc_wms_wgb 单库为基准,必须生成【全部分库表结构安全超集】作为唯一标准基线 规则:字段长度取最大值、不缩短任何列、缺失字段全部补 NULL / 默认值、字符集统一 utf8mb4、排序统一 utf8mb4_unicode_ci,所有源 MySQL 分库、下游 TiDB 全部对齐这套超集基线;
  • 处理顺序:先统一上游所有 MySQL 分库结构(超集对齐)→ 再做 DM 同步 / 全量迁移至 TiDB 跳过上游统一直接同步 TiDB 会永久存在三大问题:DM 结构校验持续报错、增量同步隐性数据截断风险、TiDB 一张表承载多套异构结构,后期业务读写、分区分片、BR 备份、CDC 同步全部埋坑;
  • 变更原则:只扩不缩、只增不删、不破坏存量数据;优先表级字符集转换,字段差异用 gh-ost/pt-online-schema-change 在线无锁变更;
  • TiDB 目标库基线:直接复用上游统一后的超集结构,不再以原始 wgb 为准,彻底消除结构校验冲突。

1)先统一所有 MySQL 分库表结构为超集;2)结构校验全部通过;3)再用 DM 同步全量 + 增量至 TiDB。
若先同步再改源库,会触发 TiDB 大量 DDL 同步、增量阻塞,风险更高。

先统一表结构(缺列补齐、类型对齐)再同步;DM 路由合并前做结构巡检。不一致时先只读校验集或灰度单库,避免目标宽表被窄表DDL冲掉。

  1. 同字段长度不一致
    tidb 用 max 长度

  2. 字符集/排序规则不一致
    字符集: tidb 设置 utf8mb4(默认)
    如果上游是向下兼容的可以,如果不兼容需要上游改造

排序规则
上游改造成一致 or 统一为下游 tidb 的排序规则

  1. 部分分库多字段或少字段
    tidb 手动建表,包含所有字段,设置 default 值
    上游只会少不会多,具体操作看官网文档 https://docs.pingcap.com/zh/tidb/stable/migrate-with-more-columns-downstream/

  2. 有些字段在部分生产库比 wgb 更长
    tidb 用 max 长

另外,上游如果有浮点数精度不一致,下游 tidb 按最长精度设置,可能产生精度偏差。 当然在从 mysql 到 tidb 不同数据库产品本身的 embedding 精度处理就存在差异,都符合 IEEE 754 就是了
https://docs.pingcap.com/zh/tidb/stable/data-type-numeric/
https://docs.pingcap.com/zh/tidb/stable/cast-functions-and-operators/

其实难的是 DDL 管理,上游如果太多,最好挑个冻结期快速切掉,避免上游执行 DDL 处理不了前功尽弃 :upside_down_face: