从MySQL到TiDB:分布式数据库迁移实战与避坑指南

引言

在业务高速增长、数据量爆炸的背景下,单机MySQL逐渐无法承载高并发与超大规模存储的需求。分布式数据库TiDB以其弹性扩展、强一致性、兼容MySQL协议等优势,成为众多企业的首选。然而,从MySQL迁移到TiDB绝非简单的数据复制,其中涉及 schema 转换、数据一致性校验、工具选型、性能调优等多个环节,稍有不慎便可能踩坑。本文基于真实项目经验,总结从 MySQL 迁移到 TiDB 的完整实战流程与常见陷阱,助你平稳完成分布式数据库迁移。

迁移前评估与规划

迁移前评估与规划

TiDB 与 MySQL 的核心差异

在动手迁移前,首先需要明确 TiDB 与 MySQL 的不同点:

  • 自增主键:TiDB 中自增主键仅保证唯一,不保证连续递增,且需注意 AUTO_INCREMENT 的锁行为。
  • 字符集与排序规则:TiDB 默认字符集为 utf8mb4,但 utf8_general_ci 等排序规则可能与 MySQL 不兼容。
  • 事务大小限制:TiDB 单事务大小限制默认 100MB(可调),大事务可能导致 OOM 或性能问题。
  • 外键与触发器:TiDB 暂不支持外键和触发器(仅语法兼容),需提前重构。
  • DDL 机制:TiDB 的 DDL 非阻塞,但 ALTER TABLE 行为与 MySQL 略有差异。

数据模型与业务兼容性检查

列出所有表的结构,重点关注:

  • 数据类型:如 ENUMSETJSON 可在 TiDB 中直接使用,但 GIS 类型需用第三方方案。
  • 索引:TiDB 支持二级索引,但 FULLTEXT 索引暂不支持。
  • 分区表:TiDB 仅支持 Range、Hash、List 分区,不支持子分区和 COLUMNS 分区。

迁移工具选择与数据迁移

迁移工具选择与数据迁移

工具对比

工具适用场景优点缺点
TiDB Lightning用于全量数据快速导入(SQL 文件或 CSV)速度极快(可达到 500GB/h)需要停机
Dumpling + TiDB Lightning从 MySQL 导出并导入支持一致性快照全量阶段需暂停写操作
DM (Data Migration)全量+增量同步,支持实时迁移支持异构 DDL 过滤与重命名配置复杂
Syncer增量同步(已弃用,建议用 DM)轻量功能有限

推荐方案:使用 Dumpling 导出全量数据,TiDB Lightning 导入,再用 DM 进行增量同步,实现零停机迁移。

全量迁移实战

# 使用 Dumpling 导出 MySQL 数据(开启一致性快照)
dumpling -h 192.168.1.100 -P 3306 -u root -p 'password' \
  -B mydb --filetype sql --threads 4 -o /data/export

# 使用 TiDB Lightning 导入到 TiDB
./tidb-lightning -config tidb-lightning.toml

配置文件 tidb-lightning.toml 示例:

[lightning]
level = "info"
file = "lightning.log"

[checkpoint]
enable = true

[tikv-importer]
# 使用 local 模式(推荐)
backend = "local"
# 临时文件目录,需足够空间
sorted-kv-dir = "/tmp/sorted-kv"

[mydumper]
data-source-dir = "/data/export"

[tidb]
host = "192.168.2.100"
port = 4000
user = "root"
password = "password"
status-port = 10080

增量同步与实时迁移

配置 DM 同步任务,通过 task.yaml 描述:

name: test-task
task-mode: all

source-id: mysql-source

mysql-instances:
  - source-id: mysql-source
    black-white-list:
      do-dbs: ["mydb"]

完成后执行 dmctl start-task task.yaml,并监控同步延迟。

避坑指南:常见问题与解决方案

坑一:自增主键冲突

现象:迁移后插入数据时出现主键冲突。
原因:TiDB 自增 ID 是基于每个 tidb-server 实例分配,迁移时若未重置自增计数器,可能导致冲突。
解决:导入前先查询 MySQL 表最大自增值,在 TiDB 中通过 ALTER TABLE t AUTO_INCREMENT = N; 跳过后序值。

坑二:大事务回滚导致性能骤降

现象:全量迁移时 TiDB 响应变慢,甚至 OOM。
原因:默认事务大小限制为 100MB,但 TiDB Lightninglocal 模式会切分数据,不易触达限制。但若使用 dumpling 导出为单条 SQL,每条可能过大。
解决:使用 --filetype csv 或分块导出;调整 TiDB 参数 tidb_max_txn_timeouttidb_mem_quota_query

坑三:字符集乱码

现象:中文数据显示为问号。
原因:MySQL 与 TiDB 字符集不一致,如 MySQL 使用 latin1 而 TiDB 默认 utf8mb4
解决:统一字符集为 utf8mb4,导出前设置 SET NAMES utf8mb4,导入时指定 --character-set-server=utf8mb4

坑四:DDL 兼容性问题

现象:迁移过程中 DDL 执行失败。
原因:TiDB 不支持某些 MySQL DDL(如 ALGORITHM=COPY 等)。
解决:使用 DM 的 filter 功能过滤或改写 DDL,或在迁移前手动替换。

坑五:数据一致性校验失败

现象:全量+增量迁移后,部分表数据不一致。
原因:增量同步时未过滤掉 DDL,导致 schema 不匹配;或出现网络延迟。
解决:使用 sync-diff-inspector 工具进行校验,比较主键或 MD5 值,并修复差异。

迁移后验证与优化

迁移后验证与优化

验证数据完整性

使用 sync-diff-inspector

sync_diff_inspector --config diff-config.toml

配置示例:

[data-sources]
[data-sources.mysql]
host = "192.168.1.100"
port = 3306
user = "root"
password = "password"
snapshot = "2023-10-01 00:00:00"

[data-sources.tidb]
host = "192.168.2.100"
port = 4000
user = "root"
password = "password"

[task]
check-all = true

[[table-config]]
schema = "mydb"
table = "*"

性能调优建议

  • 调整 Region 大小ALTER TABLE t SET REGION_NUM = 16; 避免小表热点。
  • SQL 优化:检查慢查询,利用 TiDB 的 EXPLAIN ANALYZE 分析执行计划。
  • 调整 tidb_distsql_scan_concurrency:提升全表扫描效率。

总结

从 MySQL 迁移到 TiDB 并非一蹴而就,需要细致的前期规划、正确的工具选型以及充分的测试。本文总结了实际迁移中的全流程步骤五大常见陷阱,包括自增主键、大事务、字符集、DDL 兼容性及数据一致性。遵循本文的避坑指南,可大幅降低迁移风险,确保业务平滑切换。分布式数据库迁移是一把双刃剑,用得好可为架构降本增效,用不好则可能引发线上事故。希望这份实战笔记能为你提供切实可靠的参考。

觉得内容不错?我要

评论 暂无评论
暂无评论,快来抢沙发吧~