跳到主要内容

数据库迁移实战

问题

需要将 MySQL 数据库从自建机房迁移到云上(或跨版本升级),要求零停机或极短停机,如何操作?

答案

迁移方案对比

方案停机时间复杂度数据一致性适用场景
mysqldump 导入长(小时级)小库(< 10GB
主从复制切换秒级同版本 / 跨版本
DTS 数据同步秒级上云迁移
双写方案零停机⚠️异构迁移

方案一:基于主从复制的迁移(推荐)

# Step 1: 新库与旧库建立主从
# 在新库上执行
CHANGE MASTER TO
MASTER_HOST='old-db.example.com',
MASTER_USER='repl_user',
MASTER_PASSWORD='repl_pass',
MASTER_AUTO_POSITION=1; -- GTID 模式
START SLAVE;

# 确认复制正常
SHOW SLAVE STATUS\G
# Seconds_Behind_Master: 0 -- 追平后才能切换

# Step 2: 切换前检查
# 确认数据一致
pt-table-checksum --host=old-db --databases=mydb

# Step 3: 切换(闪断窗口 < 30 秒)
# 1. 旧库设为只读
SET GLOBAL read_only = ON;
SET GLOBAL super_read_only = ON;

# 2. 等新库追平(通常几秒)
# SHOW SLAVE STATUS → Seconds_Behind_Master = 0

# 3. 新库断开复制,设为可写
STOP SLAVE;
RESET SLAVE ALL;
SET GLOBAL read_only = OFF;

# 4. 应用连接切换到新库(修改 DNS / 配置)
# 5. 验证业务正常

方案二:停机迁移(小库简单方案)

# 适合 < 10GB 的小库

# 1. 应用停止写入
# 2. 导出
mysqldump -h old-db -u root -p \
--single-transaction \
--routines --triggers --events \
--set-gtid-purged=OFF \
mydb > mydb_backup.sql

# 3. 导入新库
mysql -h new-db -u root -p mydb < mydb_backup.sql

# 4. 切换应用连接
# 5. 验证

数据校验

# 使用 pt-table-checksum 验证数据一致性
pt-table-checksum \
--host=old-db \
--user=root \
--databases=mydb \
--replicate=percona.checksums

# 查看差异
pt-table-sync \
--print \
--replicate=percona.checksums \
--host=old-db \
--databases=mydb

# 简单校验:行数对比
mysql -h old-db -e "SELECT COUNT(*) FROM mydb.users"
mysql -h new-db -e "SELECT COUNT(*) FROM mydb.users"

迁移 Checklist

步骤检查项状态
1新库版本兼容性确认
2新库参数配置与旧库对齐
3建立复制并追平
4pt-table-checksum 数据校验通过
5应用连接测试新库
6回滚方案准备(新库反向复制旧库)
7切换窗口通知业务方
8执行切换
9业务验证
10观察 24 小时,确认无问题后下线旧库

常见面试问题

Q1: 迁移过程中如何保证可以回滚?

答案

  1. 反向复制:切换前在旧库上建立对新库的复制(新主→旧从),一旦新库有问题,可以切回旧库
  2. 不立即下线旧库:切换后保留旧库 24~72 小时
  3. DNS TTL 调低:切换前将 DNS TTL 降到 60 秒,确保回切时快速生效
  4. 数据对账:切换后持续运行数据校验脚本

相关链接