0
0
0
0
博客/.../

华为云数据库迁移到 TiDB 实践方案

 tianyan  发表于  2026-05-29

1. 方案概述

1.1 背景与目标

华为云 GaussDB/RDS MySQL 是企业常用的关系型数据库服务,TiDB 作为分布式 HTAP 数据库,在以下场景具备明显优势:

维度 华为云 RDS/GaussDB TiDB
架构 单机/主从 分布式水平扩展
扩展性 垂直扩展为主 水平扩展,无上限
HTAP 不支持 原生支持(TiKV + TiFlash)
兼容性 MySQL 协议 MySQL 协议(高度兼容)
高可用 主备切换 Multi-Raft,自动容灾
数据量 TB 级遇瓶颈 PB 级

迁移目标:

  • 业务不中断,RPO = 0,RTO < 30min
  • 数据零丢失,迁移前后一致性 100%
  • 应用改动量最小化

1.2 迁移架构图

华为云                              TiDB 集群
┌──────────────────┐               ┌──────────────────────────────────┐
│  RDS/GaussDB     │               │  TiDB (SQL Layer)  x3            │
│  ┌────────────┐  │   DM/Dumpling │  TiKV (Storage)    x3+           │
│  │ 主库        │──┼──────────────▶│  TiFlash (HTAP)    x2 (可选)     │
│  │ binlog on  │  │               │  PD (调度)          x3            │
│  └────────────┘  │               └──────────────────────────────────┘
│  从库/只读副本    │                        ▲
└──────────────────┘               TiDB Data Migration (DM)

1.3 迁移流程总览

阶段一:评估         阶段二:准备         阶段三:迁移         阶段四:割接
┌──────────┐        ┌──────────┐        ┌──────────┐        ┌──────────┐
│ 兼容性   │        │ TiDB     │        │ Schema   │        │ 双写验证 │
│ 评估     │───────▶│ 集群部署 │───────▶│ + 全量   │───────▶│ 流量切换 │
│ 容量规划 │        │ 环境配置 │        │ + 增量   │        │ 业务验证 │
└──────────┘        └──────────┘        └──────────┘        └──────────┘
  1~2 周              1 周                3~7 天               1 天

2. 迁移前评估

2.1 兼容性评估

2.1.1 使用 TiDB 兼容性检查工具

bash

复制

# 安装 tidb-tools
wget https://download.pingcap.org/tidb-community-toolkit-v7.5.0-linux-amd64.tar.gz
tar -xzf tidb-community-toolkit-v7.5.0-linux-amd64.tar.gz

# 使用 sqldiff 工具检查 DDL 兼容性
./tidb-tools/bin/checker \
  -host <华为云RDS地址> \
  -port 3306 \
  -user root \
  -password <密码> \
  -database <库名>

2.1.2 手动检查清单

(1)不兼容的数据类型

sql

复制

-- 检查 ENUM/SET 类型(TiDB 支持,但有细微差异)
SELECT TABLE_NAME, COLUMN_NAME, COLUMN_TYPE
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'your_db'
  AND (COLUMN_TYPE LIKE 'enum%' OR COLUMN_TYPE LIKE 'set%');

-- 检查空间类型(TiDB 部分支持)
SELECT TABLE_NAME, COLUMN_NAME, COLUMN_TYPE
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'your_db'
  AND COLUMN_TYPE IN ('geometry','point','linestring','polygon','multipoint','multilinestring','multipolygon','geometrycollection');

(2)检查存储引擎

sql

复制

-- TiDB 只支持 InnoDB,MyISAM 需要提前处理
SELECT TABLE_NAME, ENGINE
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'your_db'
  AND ENGINE != 'InnoDB';

(3)检查不支持的 SQL 特性

sql

复制

-- 检查外键约束(TiDB 默认不强制外键)
SELECT TABLE_NAME, CONSTRAINT_NAME, REFERENCED_TABLE_NAME
FROM information_schema.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = 'your_db'
  AND REFERENCED_TABLE_NAME IS NOT NULL;

-- 检查触发器
SELECT TRIGGER_NAME, EVENT_MANIPULATION, EVENT_OBJECT_TABLE
FROM information_schema.TRIGGERS
WHERE TRIGGER_SCHEMA = 'your_db';

-- 检查存储过程
SELECT ROUTINE_NAME, ROUTINE_TYPE
FROM information_schema.ROUTINES
WHERE ROUTINE_SCHEMA = 'your_db';

(4)检查字符集

sql

复制

-- TiDB 推荐 utf8mb4
SELECT TABLE_NAME, TABLE_COLLATION
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'your_db'
  AND TABLE_COLLATION NOT LIKE 'utf8mb4%';

2.1.3 已知不兼容项处理

华为云特性 TiDB 处理方式
外键约束 set @@foreign_key_checks=0 跳过,业务层保证完整性
存储过程/函数 逐一评估,部分可直接迁移,复杂逻辑改写
触发器 迁移至应用层或使用 TiDB 的 TTL/CDC 替代
MyISAM 表 导出数据并以 InnoDB 重建
GROUP BY 隐式排序 显式加 ORDER BY
ONLY_FULL_GROUP_BY TiDB 默认开启,SQL 需整改
自增 ID 不连续 TiDB 分布式自增,不保证连续但单调递增

2.2 容量规划

sql

复制

-- 在华为云上评估数据量
SELECT 
  table_schema AS '数据库',
  ROUND(SUM(data_length + index_length) / 1024 / 1024 / 1024, 2) AS '总大小(GB)',
  ROUND(SUM(data_length) / 1024 / 1024 / 1024, 2) AS '数据(GB)',
  ROUND(SUM(index_length) / 1024 / 1024 / 1024, 2) AS '索引(GB)',
  COUNT(*) AS '表数量'
FROM information_schema.TABLES
WHERE table_schema NOT IN ('information_schema','mysql','performance_schema','sys')
GROUP BY table_schema;

-- 评估每日数据增量(通过 binlog 大小估算)
SHOW BINARY LOGS;

TiDB 集群容量建议(TiKV 3 副本):

华为云数据量 TiKV 节点数 单节点配置
< 500GB 3 节点 16C/64G/2TB SSD
500GB~2TB 3~6 节点 32C/128G/4TB SSD
2TB~10TB 6~12 节点 32C/128G/8TB SSD
> 10TB 12+ 节点 按需扩展

2.3 网络与权限评估

sql

复制

-- 确认华为云 RDS 开启 binlog(迁移增量同步必需)
SHOW VARIABLES LIKE 'log_bin';
SHOW VARIABLES LIKE 'binlog_format';
-- 需要: log_bin=ON, binlog_format=ROW

-- 检查 binlog 保留时间(建议 >= 7 天)
SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';

-- 创建迁移专用账号(最小权限原则)
CREATE USER 'migration'@'%' IDENTIFIED BY 'StrongPassword123!';
GRANT SELECT, RELOAD, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'migration'@'%';
GRANT SELECT ON mysql.* TO 'migration'@'%';

3. 环境准备

3.1 TiDB 集群部署(使用 TiUP)

bash

复制

# 1. 安装 TiUP(在中控机执行)
curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh
source ~/.bash_profile

# 2. 安装集群组件
tiup cluster

# 3. 编写集群拓扑配置文件 topology.yaml
cat > topology.yaml << 'EOF'
global:
  user: "tidb"
  ssh_port: 22
  deploy_dir: "/tidb-deploy"
  data_dir: "/tidb-data"
  
server_configs:
  tidb:
    log.slow-threshold: 300
    binlog.enable: false
    performance.max-procs: 0
  tikv:
    rocksdb.max-open-files: -1
    raftstore.capacity: 0
    storage.reserve-space: 0
  pd:
    schedule.leader-schedule-limit: 4
    schedule.region-schedule-limit: 2048
    schedule.replica-schedule-limit: 64

pd_servers:
  - host: 10.0.1.11
  - host: 10.0.1.12
  - host: 10.0.1.13

tidb_servers:
  - host: 10.0.1.21
    port: 4000
    status_port: 10080
  - host: 10.0.1.22
    port: 4000
    status_port: 10080
  - host: 10.0.1.23
    port: 4000
    status_port: 10080

tikv_servers:
  - host: 10.0.1.31
    port: 20160
    status_port: 20180
    config:
      server.labels:
        zone: "zone1"
  - host: 10.0.1.32
    port: 20160
    status_port: 20180
    config:
      server.labels:
        zone: "zone2"
  - host: 10.0.1.33
    port: 20160
    status_port: 20180
    config:
      server.labels:
        zone: "zone3"

# 如需 HTAP 功能,添加 TiFlash
tiflash_servers:
  - host: 10.0.1.41
    data_path: /tiflash-data
    
monitoring_servers:
  - host: 10.0.1.51

grafana_servers:
  - host: 10.0.1.51
EOF

# 4. 部署集群
tiup cluster deploy tidb-prod v7.5.0 topology.yaml --user root -p

# 5. 启动集群
tiup cluster start tidb-prod

# 6. 验证集群状态
tiup cluster display tidb-prod

3.2 华为云侧准备

sql

复制

-- 1. 确认开启 GTID(推荐,便于增量同步断点恢复)
SHOW VARIABLES LIKE 'gtid_mode';
SHOW VARIABLES LIKE 'enforce_gtid_consistency';
-- 如果未开启,需要配合 DBA 在维护窗口开启

-- 2. 创建迁移用户
CREATE USER 'dm_user'@'%' IDENTIFIED BY 'DmPassword@2024';
GRANT SELECT, RELOAD, LOCK TABLES, REPLICATION SLAVE, 
      REPLICATION CLIENT, TRIGGER ON *.* TO 'dm_user'@'%';
FLUSH PRIVILEGES;

-- 3. 确认网络互通(在迁移机器上测试)
mysql -h <华为云RDS地址> -P 3306 -u dm_user -p -e "SELECT 1"
mysql -h <TiDB地址> -P 4000 -u root -p -e "SELECT 1"

4. Schema 迁移

4.1 导出 Schema

bash

复制

# 使用 Dumpling 导出 Schema(仅结构,不含数据)
tiup dumpling \
  -h <华为云RDS地址> \
  -P 3306 \
  -u dm_user \
  -p "DmPassword@2024" \
  --filetype sql \
  --no-data \
  -o /data/schema_dump \
  --databases your_db1,your_db2

4.2 Schema 调整脚本

bash

复制

cat > fix_schema.sh << 'SCRIPT'
#!/bin/bash
SCHEMA_DIR="/data/schema_dump"
OUTPUT_DIR="/data/schema_fixed"
mkdir -p $OUTPUT_DIR

for f in $SCHEMA_DIR/*.sql; do
    filename=$(basename "$f")
    content=$(cat "$f")
    # 1. MyISAM → InnoDB
    content=$(echo "$content" | sed 's/ENGINE=MyISAM/ENGINE=InnoDB/g')
    # 2. 去掉 AUTO_INCREMENT 具体值
    content=$(echo "$content" | sed 's/ AUTO_INCREMENT=[0-9]*//g')
    # 3. charset 统一为 utf8mb4
    content=$(echo "$content" | sed 's/DEFAULT CHARSET=latin1/DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci/g')
    content=$(echo "$content" | sed 's/DEFAULT CHARSET=utf8\b/DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci/g')
    # 4. 去掉 COMPRESSION 选项
    content=$(echo "$content" | sed "s/COMPRESSION='[^']*'//g")
    echo "$content" > "$OUTPUT_DIR/$filename"
done
echo "Schema 调整完成"
SCRIPT
chmod +x fix_schema.sh && ./fix_schema.sh

5. 数据迁移

5.1 方案选择

数据量 迁移时间窗口 推荐工具 备注
< 100GB 不限 DM(全量+增量) 简单易用
100GB~1TB 有窗口 TiDB Lightning + DM 增量 速度最快
> 1TB 有窗口 TiDB Lightning + DM 增量 必选
任意 无停机 DM 全量+增量一体 推荐生产环境

5.2 方案 A:TiDB DM(推荐)

bash

复制

# 部署 DM 集群
cat > dm-topology.yaml << 'EOF'
master_servers:
  - host: 10.0.1.61
    port: 8261
    peer_port: 8291
worker_servers:
  - host: 10.0.1.62
    port: 8262
  - host: 10.0.1.63
    port: 8262
EOF
tiup dm deploy dm-cluster v7.5.0 dm-topology.yaml --user root -p
tiup dm start dm-cluster

yaml

复制

# task-migration.yaml
name: "huawei-to-tidb"
task-mode: all   # all = 全量 + 增量

target-database:
  host: "<TiDB地址>"
  port: 4000
  user: "root"
  password: ""

mysql-instances:
  - source-id: "huawei-rds-01"
    route-rules: ["route-rule-1"]
    filter-rules: ["filter-1"]
    mydumper-config-name: "dump-config"
    loader-config-name: "load-config"
    syncer-config-name: "sync-config"

routes:
  route-rule-1:
    schema-pattern: "your_db1"
    target-schema: "your_db1"

filters:
  filter-1:
    schema-pattern: "your_db1"
    events: ["truncate table", "drop table", "drop database"]
    action: Ignore

syncers:
  sync-config:
    worker-count: 16
    batch: 100
    safe-mode: true

bash

复制

# 启动 / 监控 / 管理任务
tiup dmctl --master-addr 10.0.1.61:8261 start-task task-migration.yaml
tiup dmctl --master-addr 10.0.1.61:8261 query-status huawei-to-tidb
tiup dmctl --master-addr 10.0.1.61:8261 pause-task huawei-to-tidb
tiup dmctl --master-addr 10.0.1.61:8261 resume-task huawei-to-tidb

5.3 方案 B:TiDB Lightning(大数据量)

bash

复制

# Step 1: Dumpling 导出
tiup dumpling -h <华为云RDS地址> -P 3306 -u dm_user -p "DmPassword@2024" \
  --consistency=flush --filetype parquet -o /data/full_dump \
  --databases your_db1,your_db2 -r 200000 --threads 8

# Step 2: Lightning 导入
cat > lightning.toml << 'EOF'
[tikv-importer]
backend = "local"
sorted-kv-dir = "/tmp/sorted-kv-dir"

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

[tidb]
host = "<TiDB地址>"
port = 4000
user = "root"
pd-addr = "10.0.1.11:2379"

[post-restore]
checksum = "required"
analyze = "optional"
EOF

tiup tidb-lightning -config lightning.toml

6. 应用层改造

6.1 连接配置(Spring Boot 示例)

properties

复制

# 修改后(TiDB 推荐参数)
spring.datasource.url=jdbc:mysql://<TiDB地址>:4000/your_db\
  ?useSSL=false\
  &characterEncoding=UTF-8\
  &useServerPrepStmts=true\
  &cachePrepStmts=true\
  &rewriteBatchedStatements=true\
  &connectionCollation=utf8mb4_unicode_ci

6.2 关键 SQL 改造点

sql

复制

-- ① 游标分页替代大 offset
-- 改前
SELECT * FROM orders ORDER BY id LIMIT 100000, 20;
-- 改后
SELECT * FROM orders WHERE id > :last_id ORDER BY id LIMIT 20;

-- ② 批量 DELETE 分批执行(事务大小限制)
DELETE FROM logs WHERE create_time < '2023-01-01' LIMIT 1000;
-- 循环执行直到影响行数为 0

-- ③ 写热点:AUTO_RANDOM 替代 AUTO_INCREMENT
CREATE TABLE orders (
    id BIGINT AUTO_RANDOM PRIMARY KEY,
    user_id INT NOT NULL,
    ...
);

-- ④ HTAP 查询强制走 TiFlash
ALTER TABLE orders SET TIFLASH REPLICA 1;
SELECT /*+ read_from_storage(tiflash[orders]) */
    DATE(created_at), SUM(amount)
FROM orders WHERE created_at >= '2024-01-01'
GROUP BY DATE(created_at);

7. 数据验证与一致性校验

7.1 sync-diff-inspector

bash

复制

cat > diff-config.toml << 'EOF'
check-thread-count = 4
export-fix-sql = true

[task]
output-dir = "./output"
source-instances = ["huawei-rds"]
target-instance = "tidb-target"
target-check-tables = ["your_db1.*"]

[data-sources.huawei-rds]
host = "<华为云RDS地址>"
port = 3306
user = "dm_user"
password = "DmPassword@2024"

[data-sources.tidb-target]
host = "<TiDB地址>"
port = 4000
user = "root"
password = ""
EOF

./sync_diff_inspector --config=diff-config.toml
cat output/summary.txt   # 如有差异生成 output/fix.sql

7.2 增量延迟监控

bash

复制

# 割接前延迟须稳定 < 3s
watch -n 5 'tiup dmctl --master-addr 10.0.1.61:8261 query-status huawei-to-tidb 2>/dev/null \
  | python3 -c "import sys,json; d=json.load(sys.stdin); \
    [print(\"Delay:\", s[\"sync\"][\"secondsBehindMaster\"], \"s\") for s in d[\"subTaskStatus\"]]"'

8. 性能调优

sql

复制

-- 统计信息收集(迁移完成后立即执行)
ANALYZE TABLE your_db1.orders;
SET GLOBAL tidb_auto_analyze_ratio = 0.1;
SET GLOBAL tidb_auto_analyze_start_time = '02:00 +0800';
SET GLOBAL tidb_auto_analyze_end_time   = '06:00 +0800';

-- 热点 Region 处理
ALTER TABLE orders MODIFY id BIGINT AUTO_RANDOM;
ALTER TABLE logs SHARD_ROW_ID_BITS = 4 PRE_SPLIT_REGIONS = 4;

-- 检查热点 Region
SELECT region_id, written_bytes, read_bytes
FROM information_schema.TIKV_REGION_STATUS
ORDER BY written_bytes DESC LIMIT 10;

9. 割接方案

9.1 灰度切换时间线

T0  DM 增量同步运行中(华为云 → TiDB)
T1  切 5% 读流量到 TiDB,观察 15min
T2  逐步扩大:30% → 50% → 100%(每步间隔 30min)
T3  维护窗口(01:00~02:00):停写 → 等延迟为 0 → 切写流量 → 停 DM
T4  割接完成,华为云保留 7 天作回滚备用

9.2 割接操作脚本

bash

复制

# 1. 确认 DM 延迟
tiup dmctl --master-addr 10.0.1.61:8261 query-status huawei-to-tidb \
  | grep -E "secondsBehindMaster|syncerBinlog"

# 2. 华为云设只读
mysql -h <华为云RDS地址> -P 3306 -u admin -p -e "SET GLOBAL read_only = ON;"

# 3. 等待同步追平
while true; do
    DELAY=$(tiup dmctl --master-addr 10.0.1.61:8261 query-status huawei-to-tidb 2>/dev/null \
      | python3 -c "import sys,json; d=json.load(sys.stdin); \
        print(d['subTaskStatus'][0]['sync']['secondsBehindMaster'])" 2>/dev/null)
    echo "延迟: ${DELAY}s"; [ "$DELAY" = "0" ] && break; sleep 5
done

# 4. 最终数据量校验
HW_CNT=$(mysql -h <华为云地址> -P 3306 -u dm_user -pDmPassword@2024 -se "SELECT COUNT(*) FROM your_db1.orders")
TD_CNT=$(mysql -h <TiDB地址> -P 4000 -u root -p -se "SELECT COUNT(*) FROM your_db1.orders")
[ "$HW_CNT" = "$TD_CNT" ] && echo "✅ 可以割接" || { echo "❌ 不一致!"; exit 1; }

# 5. 切写流量到 TiDB(修改负载均衡/DNS/应用配置)

# 6. 停止 DM 任务
tiup dmctl --master-addr 10.0.1.61:8261 stop-task huawei-to-tidb10. 回滚预案

10.1 触发条件

指标 警戒值 回滚触发
接口错误率 > 0.5% > 2%
P99 延迟 > 原来 2x > 原来 5x
DB 连接失败 > 0 持续 > 30s

10.2 回滚脚本

bash

复制

# 解除华为云只读
mysql -h <华为云RDS地址> -P 3306 -u admin -p -e "SET GLOBAL read_only = OFF;"
# 切流量回华为云(负载均衡/DNS)
# 启动反向同步(TiDB → 华为云,补偿割接后增量)
tiup dmctl --master-addr 10.0.1.61:8261 start-task task-reverse-sync.yaml

11. 监控与运维

bash

复制

# Grafana 监控(端口 3000)
# Dashboard:TiDB Summary / TiKV Details / PD

# 扩容 TiKV(不停业务)
tiup cluster scale-out tidb-prod scale-out-tikv.yaml

# 滚动升级
tiup cluster upgrade tidb-prod v7.6.0

# 备份(BR)
tiup br backup full \
  --pd 10.0.1.11:2379 \
  --storage s3://your-bucket/backup/$(date +%Y%m%d)

关键告警规则:

yaml

复制

groups:
- name: tidb-critical
  rules:
  - alert: TiDBDown
    expr: up{job="tidb"} == 0
  - alert: TiKVStorageUsage
    expr: tikv_store_size_bytes{type="used"} / tikv_store_size_bytes{type="capacity"} > 0.8
    for: 10m
  - alert: TiDBSlowQuery
    expr: histogram_quantile(0.99, rate(tidb_server_slow_query_process_duration_seconds_bucket[5m])) > 1
    for: 5m

12. 常见问题 FAQ

Q1:DM 报 Error 1236: Could not find first log file name

bash

复制

# binlog 被清理,重置任务
tiup dmctl --master-addr 10.0.1.61:8261 stop-task huawei-to-tidb
tiup dmctl --master-addr 10.0.1.61:8261 delete-meta huawei-to-tidb
tiup dmctl --master-addr 10.0.1.61:8261 start-task task-migration.yaml

Q2:Lightning 报 checksum mismatch

bash

复制

tiup tidb-lightning-ctl --config lightning.toml --checkpoint-error-destroy=all
tiup tidb-lightning -config lightning.toml

Q3:写热点 TiKV 节点 CPU 100%

sql

复制

-- pre-split 分裂 Region
ALTER TABLE orders SPLIT BY (100000),(200000),(300000),(400000),(500000);
-- 或改用 AUTO_RANDOM
ALTER TABLE orders MODIFY id BIGINT AUTO_RANDOM;

Q4:何时可以停止 DM 任务

bash

复制

# 两侧 MAX(id) 相同且延迟为 0,即可安全停止
mysql -h <华为云地址> -se "SELECT MAX(id) FROM your_db1.orders"
mysql -h <TiDB地址> -P 4000 -se "SELECT MAX(id) FROM your_db1.orders"

0
0
0
0

声明:本文转载于 https://pingkai.cn/tidbcommunity/blog/62a91f79/edit

评论
暂无评论