0
0
0
0
博客/.../

TiDB 数据迁移与同步实战

 北南南北  发表于  2026-05-29

一、数据迁移概述

1.1 迁移场景

从传统数据库迁移到 TiDB 是常见需求,主要场景包括:

场景 工具 数据量级
小数据量 MySQL 迁移 Dumpling + TiDB Lightning < 500GB
大数据量 MySQL 迁移 DM(Data Migration) 500GB ~ 数 TB
全量 + 增量同步 DM 持续同步
CSV/SQL 文件导入 TiDB Lightning 任何来源
逻辑导出导入 Dumpling + mysql client 小数据量
持续复制到 Kafka TiCDC 实时 CDC

1.2 迁移流程概览

完整迁移流程:

┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐
│ 评估兼容性 │───>│ 全量迁移  │───>│ 增量同步  │───>│ 切换流量  │
└──────────┘    └──────────┘    └──────────┘    └──────────┘
   │              │               │               │
   v              v               v               v
 检查不兼容    导出数据        追平增量       验证数据
 特性列表      导入 TiDB       数据校验       切换应用

二、使用 Dumpling + TiDB Lightning 迁移

2.1 Dumpling 导出

Dumpling 是 PingCAP 开发的逻辑备份工具,兼容 MySQL 协议:

# 从 MySQL 导出数据
dumpling \
    -h 127.0.0.1 \
    -P 3306 \
    -u root \
    -p 'password' \
    -B mydb \
    -f 'mydb.table[1-9]' \
    -r 200000 \
    -t 8 \
    -o /data/export/mydb

参数说明:

参数 含义
-B 导出指定数据库
-f 过滤规则(只导出特定表)
-r 每个文件的最大行数(用于并发)
-t 并发线程数
-o 输出目录

导出结果:

/data/export/mydb/
├── mydb-schema.sql          # 建表语句
├── mydb.users.000000000.sql # 表数据(按行切分)
├── mydb.users.000000001.sql
├── mydb.orders.000000000.sql
└── metadata                 # 元信息(binlog 位置等)

2.2 TiDB Lightning 导入

TiDB Lightning 是高性能的全量数据导入工具:

# 配置文件 lightning.toml
[lightning]
level = "info"
file = "tidb-lightning.log"

[tikv-importer]
# 导入模式: "local"(推荐,最快)或 "tidb"
backend = "local"
# 排序后的 KV 文件目录
sorted-kv-dir = "/tmp/sorted-kv"

[mydumper]
# 数据源目录
data-source-dir = "/data/export/mydb"

[mydumper.csv]
separator = ','
delimiter = '"'
header = false

[tidb]
# TiDB 连接信息
host = "127.0.0.1"
port = 4000
user = "root"
password = ""
status-port = 10080

# 导入
tiup tidb-lightning -config lightning.toml

导入模式对比

模式 速度 对 TiKV 影响 适用场景
Local 最快(可达 100GB/小时) 大(需要独占) 大批量首次导入
TiDB 较慢 小(正常写入) 增量导入或小数据量

2.3 校验数据

# 使用 sync-diff-inspector 校验数据(所有配置通过 config 文件指定)
tiup sync-diff-inspector -C config.yaml
# config.yaml
data-sources:
  mysql_source:
    host: "127.0.0.1"
    port: 3306
    user: "root"
    password: "password"
  tidb_target:
    host: "127.0.0.1"
    port: 4000
    user: "root"
    password: ""

task:
  output-dir: "./output"
  source-instances:
    - mysql_source
  target-instance: tidb_target
  target-check-tables:
    - "mydb.*"

三、使用 DM 从 MySQL 迁移

3.1 DM 简介

DM(Data Migration)是 TiDB 官方推出的数据迁移工具,支持:

  • 全量迁移:从 MySQL 导出现有数据
  • 增量同步:持续同步 MySQL 的 binlog 到 TiDB
  • 分库分表合并:将多个 MySQL 实例的库表合并到 TiDB 的一张表
DM 架构:

  ┌─────────┐
  │ DM-master│  调度和管理
  └────┬────┘
       │
  ┌────┴────┐
  v         v
┌─────┐  ┌─────┐
│DM-W1│  │DM-W2│  Worker,执行迁移任务
└──┬──┘  └──┬──┘
   │        │
   v        v
MySQL-1  MySQL-2  →  TiDB

3.2 部署 DM 集群

# DM 集群拓扑
cat > dm-topology.yaml << EOF
master_servers:
  - host: 10.0.1.50
    port: 8261

worker_servers:
  - host: 10.0.1.51
    port: 8262
    deploy_dir: "/dm-deploy"
    data_dir: "/dm-data"
EOF

# 部署
tiup dm deploy dm-cluster v8.5.0 dm-topology.yaml

# 启动
tiup dm start dm-cluster

3.3 配置迁移任务

# task.yaml — 全量 + 增量迁移配置
name: "mysql-to-tidb"
task-mode: "all"  # all = 全量 + 增量

# 上游 MySQL 配置
mysql-instances:
  - source-id: "mysql-source-1"
    block-allow-list: "global"
    mydumper-config-name: "global"
    loader-config-name: "global"
    syncer-config-name: "global"

# 下游 TiDB 配置
target-database:
  host: "10.0.1.14"
  port: 4000
  user: "root"
  password: ""

# 库表过滤
block-allow-list:
  global:
    do-dbs: ["mydb"]
    do-tables:
      - db-name: "mydb"
        tbl-name: "~^table_.*"  # 正则匹配

# 全量导出配置
mydumper-config-name: "global"
mydumpers:
  global:
    rows: 200000
    threads: 8

# 全量导入配置
loader-config-name: "global"
loaders:
  global:
    pool-size: 16
    dir: "./dumped_data"

# 增量同步配置
syncer-config-name: "global"
syncers:
  global:
    worker-count: 16
    batch: 100

3.4 启动迁移任务

# 配置数据源
cat > source1.yaml << EOF
source-id: "mysql-source-1"
from:
  host: "192.168.1.100"
  port: 3306
  user: "root"
  password: "password"
EOF

# 创建数据源
tiup dmctl --master-addr 10.0.1.50:8261 operate-source create source1.yaml

# 启动迁移任务
tiup dmctl --master-addr 10.0.1.50:8261 start-task task.yaml

# 查看任务状态
tiup dmctl --master-addr 10.0.1.50:8261 query-status mysql-to-tidb

3.5 迁移过程中的操作

# 暂停任务
tiup dmctl --master-addr 10.0.1.50:8261 pause-task mysql-to-tidb

# 恢复任务
tiup dmctl --master-addr 10.0.1.50:8261 resume-task mysql-to-tidb

# 停止任务
tiup dmctl --master-addr 10.0.1.50:8261 stop-task mysql-to-tidb

# 查看当前 binlog 同步位置
tiup dmctl --master-addr 10.0.1.50:8261 query-status mysql-to-tidb

3.6 切换流量

当增量同步追平后,可以进行切换:

-- 1. 确认同步延迟为 0
-- 在 DM 中查看 syncer 的 binlog 位置
-- 对比 MySQL 当前的 binlog 位置

-- 2. 停止 MySQL 写入(在应用层)
-- 确保不再有新的写入

-- 3. 等待 DM 追平最后一个 binlog 事件

-- 4. 验证数据一致性
-- 使用 sync-diff-inspector

-- 5. 将应用连接切换到 TiDB

-- 6. 停止 DM 增量同步
tiup dmctl --master-addr 10.0.1.50:8261 stop-task mysql-to-tidb

四、分库分表合并迁移

4.1 场景

MySQL 分库分表:

  db_order_01.order    ─┐
  db_order_02.order    ─┼──> TiDB order_db.orders
  db_order_03.order    ─┘

每个库包含部分用户的数据,需要合并到 TiDB 的一张表中。

4.2 配置分库分表合并

# task-sharding.yaml
name: "sharding-merge"
task-mode: "all"

mysql-instances:
  - source-id: "mysql-source-1"
    block-allow-list: "global"
    route-rules: ["db-route", "table-route"]

target-database:
  host: "10.0.1.14"
  port: 4000
  user: "root"

# 路由规则:将多个库映射到一个库
routes:
  db-route:
    schema-pattern: "db_order_*"
    target-schema: "order_db"
  table-route:
    schema-pattern: "db_order_*"
    table-pattern: "order"
    target-schema: "order_db"
    target-table: "orders"

block-allow-list:
  global:
    do-dbs: ["db_order_*"]
    do-tables:
      - db-name: "db_order_*"
        tbl-name: "order"

五、TiCDC 实时数据同步

5.1 TiCDC 简介

TiCDC 是 TiDB 的变更数据捕获(CDC)工具,可以实时捕获 TiDB 的数据变更并同步到下游:

TiCDC 架构:

  ┌────────┐    TiCDC     ┌─────────┐
  │  TiDB  │ ──────────> │ Kafka   │
  │ (上游)  │   Changefeed  └─────────┘
  └────────┘
                  │
                  v
            ┌─────────┐
            │  MySQL  │  (下游,可以是另一个 TiDB)
            └─────────┘
                  │
                  v
            ┌─────────────┐
            │ 云存储服务   │ (S3, GCS, 等)
            └─────────────┘

5.2 部署 TiCDC

TiCDC 通常与 TiDB 集群一起部署:

# topology.yaml 中添加
cdc_servers:
  - host: 10.0.1.60
    port: 8300
    deploy_dir: "/tidb-deploy/cdc-8300"
  - host: 10.0.1.61
    port: 8300
    deploy_dir: "/tidb-deploy/cdc-8300"
tiup cluster scale-out tidb-cluster cdc-topology.yaml

5.3 创建 Changefeed

# 创建同步到 MySQL 的 Changefeed
# 注意:v7.0+ 已移除 --sort-engine 参数(unified sorter 成为默认)
tiup cdc cli changefeed create \
    --server=http://10.0.1.60:8300 \
    --sink-uri="mysql://root:password@10.0.2.100:3306/?time-zone=UTC" \
    --changefeed-id="tidb-to-mysql"

# 创建同步到 Kafka 的 Changefeed
tiup cdc cli changefeed create \
    --server=http://10.0.1.60:8300 \
    --sink-uri="kafka://10.0.2.200:9092/tidb-cdc-topic?protocol=canal-json" \
    --changefeed-id="tidb-to-kafka"

# 同步到云存储(S3)
tiup cdc cli changefeed create \
    --server=http://10.0.1.60:8300 \
    --sink-uri="s3://bucket-name/prefix?access-key=xxx&secret-access-key=xxx" \
    --changefeed-id="tidb-to-s3"

5.4 管理 Changefeed

# 查看所有 Changefeed
tiup cdc cli changefeed list --server=http://10.0.1.60:8300

# 查看特定 Changefeed 状态
tiup cdc cli changefeed query --server=http://10.0.1.60:8300 \
    --changefeed-id tidb-to-mysql

# 暂停 Changefeed
tiup cdc cli changefeed pause --server=http://10.0.1.60:8300 \
    --changefeed-id tidb-to-mysql

# 恢复 Changefeed
tiup cdc cli changefeed resume --server=http://10.0.1.60:8300 \
    --changefeed-id tidb-to-mysql

# 删除 Changefeed
tiup cdc cli changefeed remove --server=http://10.0.1.60:8300 \
    --changefeed-id tidb-to-mysql

5.5 过滤同步的表

# 只同步特定库表(通过配置文件指定过滤规则)
# filter-rules.toml:
# [filter]
# rules = ["mydb.*", "!mydb.logs_*"]
tiup cdc cli changefeed create \
    --server=http://10.0.1.60:8300 \
    --sink-uri="mysql://root@10.0.2.100:3306/" \
    --changefeed-id="filtered-sync" \
    --config filter-rules.toml
# 同步 mydb 下所有表,除了 logs_ 开头的表

六、迁移中的兼容性问题

6.1 常见不兼容特性

MySQL 特性 TiDB 支持情况 处理方式
存储过程 有限支持 迁移到应用层
触发器 不支持 迁移到应用层
外键 6.x 起支持 检查版本
空间索引 有限支持 评估影响
全文索引 6.0+ 支持 检查版本
自定义函数 不支持 迁移到应用层
VIEW 支持 一般无需处理

6.2 迁移前检查

# 使用 DM 的前置检查
tiup dmctl --master-addr 10.0.1.50:8261 check-task task.yaml

6.3 数据类型映射

MySQL 类型 TiDB 类型 说明
INT INT 完全兼容
VARCHAR VARCHAR 完全兼容
TIMESTAMP TIMESTAMP 行为一致
ENUM ENUM 兼容
SET SET 兼容
GEOMETRY GEOMETRY 6.0+ 支持

七、迁移最佳实践

7.1 迁移前

  1. 评估兼容性:检查不兼容特性并制定方案
  2. 压测 TiDB:验证 TiDB 能承受目标负载
  3. 准备回滚方案:确保迁移失败时能回退到 MySQL
  4. 选择低峰窗口:减少对用户的影响

7.2 迁移中

  1. 先做全量迁移:导出 MySQL 数据,导入 TiDB
  2. 开启增量同步:追平全量后的增量数据
  3. 多次演练:在测试环境完整演练迁移流程
  4. 数据校验:使用 sync-diff-inspector 验证一致性

7.3 切换时

  1. 停止 MySQL 写入:在应用层面停写
  2. 等待追平:等增量同步延迟为 0
  3. 最终校验:再次确认数据一致
  4. 切换 DNS/连接串:将应用指向 TiDB
  5. 观察运行:监控 TiDB 状态,确认正常

7.4 切换后

  1. 保留 MySQL 数据:至少保留 1-2 周作为备份
  2. 持续监控:关注性能指标和错误日志
  3. 逐步优化:根据实际负载调整配置

0
0
0
0

版权声明:本文为 TiDB 社区用户原创文章,遵循 CC BY-NC-SA 4.0 版权协议,转载请附上原文出处链接和本声明。

评论
暂无评论