本文系统梳理了数据迁移的核心知识与实践方法。
主要内容包括:
1)数据迁移概念(类比搬家过程)及应用场景(国产化替代、数仓建设等);
2)标准化三步流程:模型迁移(注意数据类型/分区差异)、数据迁移(Shell/Sqoop两种方式)、数据验证(4维度校验);
3)重点工具Sqoop的实战指南(参数详解、并行原理、批量脚本);
4)完整的数据验证方案(行数比对、MD5校验等);
5)面试高频问题解析。
文章提供可操作的练习任务,强调迁移过程中数据类型转换、并行优化和严格验证的重要性,适合开发者快速掌握这一关键技术。
这是非常实用的数据迁移 笔记,我帮你重新梳理优化,让你理解为什么做、怎么做、注意事项。
这个知识点在面试和实际项目中都非常重要。
📚 数据迁移 笔记优化版
一、什么是数据迁移?(一句话理解)
数据迁移 = 把老系统的数据&脚本搬到新平台
通俗类比:
-
你家搬新房:旧家具→打包→运输→搬到新家→摆放整齐
-
数据迁移:旧库数据→抽取→转换→写入新库→验证正确
二、为什么要做数据迁移?(背景)
2.1 国产化替代(你笔记里提到的)
text
美国限制高科技产品出口
↓
国内企业不能用Oracle/IBM等商业软件
↓
必须换成国产数据库(华为GaussDB、阿里OceanBase、TiDB等)
↓
需要把老系统数据迁移到新平台
2.2 其他场景
| 场景 | 说明 |
|---|---|
| 数仓建设 | 业务库 → 数仓ODS层 |
| 技术升级 | Hadoop 2.x → 3.x |
| 云迁移 | 自建机房 → 阿里云/腾讯云 |
| 合并拆分 | 公司合并,数据整合 |
三、数据迁移三步走(核心框架)
text
第1步:模型迁移(建表)
↓
第2步:历史数据及脚本迁移(导数据)
↓
第3步:数据验证(对账)
3.1 模型迁移(表迁移)
做什么: 在目标库创建同等结构的表
注意点:
| 注意点 | 说明 | 例子 |
|---|---|---|
| 数据类型差异 | 不同数据库类型不同 | MySQL的INT → Hive的INT Oracle的NUMBER → Hive的DECIMAL |
| 分区/分桶 | Hive特有的优化手段 | 按日期分区:PARTITIONED BY (dt STRING) |
| 存储格式 | 不同格式性能不同 | 文本格式 → Parquet/ORC(列式存储) |
| 字符集 | 避免中文乱码 | 统一用UTF-8 |
示例:MySQL → Hive 数据类型映射
| MySQL类型 | Hive类型 | 注意 |
|---|---|---|
| INT | INT | 直接对应 |
| BIGINT | BIGINT | 直接对应 |
| VARCHAR(n) | STRING | Hive用STRING |
| DATETIME | STRING | 存成字符串,或用TIMESTAMP |
| DECIMAL(10,2) | DECIMAL(10,2) | 保持一致 |
3.2 历史数据及脚本迁移
做什么:
-
把老数据导出来,导进新库
-
把ETL脚本重写(适配新平台)
注意点:
| 注意点 | 说明 | 解决方案 |
|---|---|---|
| 字符集编码 | 避免乱码 | 统一UTF-8,导出时指定字符集 |
| 迁移效率 | 数据量大时很慢 | 用Sqoop/DataX并行迁移,分配资源 |
| 脚本逻辑 | SQL方言不同 | Oracle PL/SQL → Hive SQL重写 |
3.3 数据验证(最重要!)
做什么: 确保迁移后的数据准确无误
验证维度:
text
维度1:行数验证
源表行数 == 目标表行数
维度2:内容验证
抽样对比数据内容是否一致
维度3:关键指标验证
SUM(金额)、COUNT(DISTINCT 用户) 等指标对比
维度4:业务逻辑验证
跑几个业务SQL,看结果是否一致
四、数据迁移两种方式对比
| 方式 | 工具 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|---|
| Shell脚本 | MySQL + Hive命令 | 小数据量、简单迁移 | 灵活、可控 | 慢、不支持并行 |
| ETL工具 | Sqoop、DataX | 大数据量、生产环境 | 快、支持并行、断点续传 | 需要学习工具 |
五、方式一:Shell脚本迁移(你笔记里的)
5.1 完整流程解析
bash
#!/bin/bash
#### Step 1:在目标库建表
hive -e "
use a2608;
drop table if exists hive_chongzhi;
create table hive_chongzhi(
id int,
ename string,
amount int,
dt string
)
row format delimited fields terminated by '\t' # 字段分隔符
"
#### Step 2:获取源端数据到中间文件
mkdir -p /home/hadoop/2608/test
# 导出MySQL数据,去掉表头
mysql -e "select * from lee.t_chongzhi order by id" > /home/hadoop/2608/test/data
sed -i '1d' /home/hadoop/2608/test/data # 删除第一行(列名)
#### Step 3:加载数据到Hive
hive -e "
use a2608;
load data local inpath '/home/hadoop/2608/test/data' into table hive_chongzhi
"
#### Step 4:数据校验
# 4.1 导出Hive数据
rm -rf /home/hadoop/2608/test/data_bak
hadoop fs -get '/user/hive/warehouse/a2608.db/hive_chongzhi/data' '/home/hadoop/2608/test/data_bak'
# 4.2 行数对比
lin_1=$(cat /home/hadoop/2608/test/data | wc -l)
lin_2=$(cat /home/hadoop/2608/test/data_bak | wc -l)
if [ $lin_1 -eq $lin_2 ]; then
echo "hive 表数据行数跟 mysql 表数据行数一致!"
fi
# 4.3 随机抽样10条对比内容
flag=0
for((i=1;i<=10;i++)); do
x=$[$RANDOM % $lin_1 + 1] # 随机行号
con_1=$(cat /home/hadoop/2608/test/data | head -$x | tail -1)
con_2=$(cat /home/hadoop/2608/test/data_bak | head -$x | tail -1)
if [ "$con_1" != "$con_2" ]; then
flag=1
fi
done
if [ $flag -eq 0 ]; then
echo "源库跟目标库抽样对比无差异!"
else
echo "数据比对有问题,请检查"
fi
5.2 这个脚本的问题(面试可以说)
| 问题 | 说明 | 改进方案 |
|---|---|---|
| 全量导出到本地 | 数据量大时磁盘爆了 | 用Sqoop直接导入HDFS |
| 单线程 | 速度慢 | 用Sqoop的-m参数并行 |
| 随机抽样不严谨 | 可能漏掉问题数据 | 全量MD5比对或用工具 |
六、方式二:Sqoop迁移(生产推荐)
6.1 Sqoop是什么?
Sqoop = 关系型数据库 ↔ Hadoop 的数据传输工具
text
MySQL/Oracle/PostgreSQL ←→ Sqoop ←→ HDFS/Hive/HBase
6.2 单表迁移示例
bash
sqoop import \
--connect jdbc:mysql://192.168.5.100:3306/lee \
--username root \
--password 123456 \
--table emp \
--fields-terminated-by "\t" \
--lines-terminated-by "\n" \
--hive-import \
--hive-overwrite \
--create-hive-table \
--delete-target-dir \
--hive-database a2608 \
--hive-table hive_emp \
-m 1
6.3 参数详解(背下来)
| 参数 | 作用 | 例子 |
|---|---|---|
--connect |
数据库连接URL | jdbc:mysql://ip:3306/db |
--username |
用户名 | root |
--password |
密码 | 123456 |
--table |
要导入的表 | emp |
--fields-terminated-by |
列分隔符 | "\t"(制表符) |
--hive-import |
导入到Hive | 不加则导入HDFS |
--hive-overwrite |
覆盖已有数据 | 慎用! |
--create-hive-table |
自动创建Hive表 | 会自动映射类型 |
--hive-database |
Hive数据库名 | a2608 |
--hive-table |
Hive表名 | hive_emp |
-m |
并行度 | -m 4(4个并发) |
6.4 并行迁移原理
bash
# 指定主键和并行度
sqoop import \
--connect jdbc:mysql://... \
--table emp \
--split-by id \ # 按id字段切分
-m 4 # 4个并发
# Sqoop会生成4个查询:
# SELECT * FROM emp WHERE id >= 1 AND id < 2500
# SELECT * FROM emp WHERE id >= 2500 AND id < 5000
# SELECT * FROM emp WHERE id >= 5000 AND id < 7500
# SELECT * FROM emp WHERE id >= 7500 AND id <= 10000
6.5 批量迁移所有表
bash
#!/bin/bash
# 获取MySQL中所有表名
mysql -e "use lee;show tables;" | grep -v "Tables_in_lee" | while read line;
do
sqoop import \
--connect jdbc:mysql://192.168.5.100:3306/lee \
--username root \
--password 123456 \
--table $line \
--fields-terminated-by "\t" \
--hive-import \
--hive-overwrite \
--create-hive-table \
--delete-target-dir \
--hive-database a2608 \
--hive-table hive__${line} \ # 加前缀
-m 1
done
七、数据验证的完整方案
7.1 行数验证(最简单)
sql
-- MySQL
SELECT COUNT(*) FROM t_chongzhi;
-- Hive
SELECT COUNT(*) FROM hive_chongzhi;
7.2 关键指标验证
sql
-- 验证金额总和
-- MySQL
SELECT SUM(amount) FROM t_chongzhi;
-- Hive
SELECT SUM(amount) FROM hive_chongzhi;
-- 验证唯一值数量
SELECT COUNT(DISTINCT user_id) FROM t_user;
SELECT COUNT(DISTINCT user_id) FROM hive_user;
7.3 全量MD5验证(最严谨)
bash
# 导出MySQL数据并计算MD5
mysql -e "SELECT * FROM t_chongzhi ORDER BY id" > mysql_data.txt
md5sum mysql_data.txt
# 导出Hive数据并计算MD5
hive -e "SELECT * FROM hive_chongzhi ORDER BY id" > hive_data.txt
md5sum hive_data.txt
# 对比两个MD5值
7.4 自动化验证脚本
bash
#!/bin/bash
# 配置
MYSQL_TABLE="t_chongzhi"
HIVE_TABLE="hive_chongzhi"
DB="a2608"
# 1. 行数对比
mysql_count=$(mysql -e "SELECT COUNT(*) FROM $MYSQL_TABLE" | tail -1)
hive_count=$(hive -e "SELECT COUNT(*) FROM $DB.$HIVE_TABLE" | tail -1)
if [ $mysql_count -eq $hive_count ]; then
echo "✅ 行数一致: $mysql_count"
else
echo "❌ 行数不一致: MySQL=$mysql_count, Hive=$hive_count"
exit 1
fi
# 2. 金额总和对比
mysql_sum=$(mysql -e "SELECT SUM(amount) FROM $MYSQL_TABLE" | tail -1)
hive_sum=$(hive -e "SELECT SUM(amount) FROM $DB.$HIVE_TABLE" | tail -1)
if [ "$mysql_sum" == "$hive_sum" ]; then
echo "✅ 金额总和一致: $mysql_sum"
else
echo "❌ 金额总和不一致: MySQL=$mysql_sum, Hive=$hive_sum"
fi
echo "✅ 数据验证通过"
八、面试重点(背下来)
Q1:你们做过数据迁移吗?怎么做的?
做过。我们当时要把MySQL的业务库迁移到Hive数仓。主要分三步:
模型迁移:在Hive建同样的表,注意数据类型和分区
数据迁移:用Sqoop并行导入,设置合理的并行度
数据验证:对比行数、关键指标、抽样内容
Q2:Sqoop和DataX的区别?
| 维度 | Sqoop | DataX |
|---|---|---|
| 作者 | Apache | 阿里 |
| 支持数据库 | 多(MySQL/Oracle/PostgreSQL) | 更丰富(30+) |
| 性能 | 高 | 高 |
| 社区 | 活跃 | 国内活跃 |
Q3:数据量很大(TB级)怎么迁移?
用Sqoop并行(-m 参数设置10-20个并发)
按日期分批迁移(如每天的数据单独迁移)
避开业务高峰期(凌晨执行)
用压缩传输(--compress)
Q4:迁移过程中数据不一致怎么办?
先暂停迁移
找出不一致的行(用JOIN对比)
分析原因(类型转换?字符集?)
修复后重新迁移这部分数据
全部验证通过后再切换业务
Q5:你们迁移的频次?
历史数据一次性迁移(全量),增量数据按天同步(每天凌晨)
九、你今天必须动手做的练习
练习1:Sqoop单表迁移
bash
# 1. 确认MySQL有测试表
mysql -uroot -p123456 -e "SELECT * FROM lee.t_chongzhi"
# 2. 用Sqoop迁移到Hive
sqoop import \
--connect jdbc:mysql://192.168.5.100:3306/lee \
--username root \
--password 123456 \
--table t_chongzhi \
--hive-import \
--hive-database a2608 \
--hive-table hive_chongzhi \
--fields-terminated-by "\t" \
-m 1
# 3. 验证Hive表
hive -e "SELECT * FROM a2608.hive_chongzhi"
练习2:编写验证脚本
bash
# 写一个脚本,对比MySQL和Hive的行数
# 提示:用mysql -e 和 hive -e 获取count
练习3:处理增量数据
bash
# 假设每天有新数据,怎么只迁移昨天的数据?
# 提示:用--where参数
sqoop import \
--where "dt = '2025-05-28'" \
--table t_chongzhi
📌 总结:数据迁移核心要点
text
┌─────────────────────────────────────────────┐
│ 数据迁移三步走 │
├─────────────────────────────────────────────┤
│ 1. 模型迁移 │
│ → 数据类型、分区、存储格式、字符集 │
├─────────────────────────────────────────────┤
│ 2. 数据迁移 │
│ → 小数据:Shell脚本 │
│ → 大数据:Sqoop/DataX并行 │
├─────────────────────────────────────────────┤
│ 3. 数据验证 │
│ → 行数对比、指标对比、内容抽样、MD5全量 │
└─────────────────────────────────────────────┘
🎯 你现在需要做什么
-
确认教室环境:Sqoop是否已安装?
bash
which sqoop sqoop version -
跑通Sqoop示例 :把MySQL的
t_chongzhi表迁移到Hive -
把报错或结果发我,我帮你解决
告诉我:
-
Sqoop命令执行成功了吗?
-
Hive里有数据了吗?
-
行数对比一致吗?