引言
在业务高速增长、数据量爆炸的背景下,单机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 略有差异。
数据模型与业务兼容性检查
列出所有表的结构,重点关注:
- 数据类型:如
ENUM、SET、JSON可在 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 Lightning 的 local 模式会切分数据,不易触达限制。但若使用 dumpling 导出为单条 SQL,每条可能过大。
解决:使用 --filetype csv 或分块导出;调整 TiDB 参数 tidb_max_txn_timeout 和 tidb_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 兼容性及数据一致性。遵循本文的避坑指南,可大幅降低迁移风险,确保业务平滑切换。分布式数据库迁移是一把双刃剑,用得好可为架构降本增效,用不好则可能引发线上事故。希望这份实战笔记能为你提供切实可靠的参考。
觉得内容不错?我要