mysql大表迁移需分批迁移、在线变更和数据校验:按主键分片导出导入,用pt-online-schema-change实现无锁迁移,或应用层双写+灰度切换;迁移后须校验一致性、重建索引、重置自增ID并核对权限与字符集。

MySQL大表迁移不能直接用CREATE table ... AS select或mysqldump全量导出导入,否则锁表时间长、业务中断久、磁盘和内存压力大。核心思路是:分批迁移 + 在线变更 + 数据校验。
分批次导出导入(避免锁表和OOM)
对上亿行的表,按主键或自增ID切片导出,每次处理10万~50万行,用mysqldump --where或SELECT ... INTO OUTFILE配合LOAD DATA INFILE。
- 例如按ID范围导出:
mysqldump -u user -p db table --where="id BETWEEN 1 AND 100000" > part1.sql - 目标库先建好空表(含索引、字符集、引擎等完全一致),再逐片导入
- 导入时加
SET unique_checks=0; SET foreign_key_checks=0;提速,完后恢复
使用pt-online-schema-change(在线无锁迁移)
Percona Toolkit中的pt-online-schema-change适合不停服场景,它通过触发器实时同步增量数据,迁移完成后自动切换表。
- 命令示例:
pt-online-schema-change --alter "ENGINE=InnoDB" D=db,t=big_table --execute - 要求源表必须有主键或唯一索引,且不能有外键依赖
- 迁移中会创建影子表、触发器和拷贝数据,需预留足够磁盘空间(至少2倍原表大小)
应用层双写 + 渐进灰度(最稳妥的业务级方案)
适用于无法停服、对一致性要求极高、或跨版本/跨引擎(如MyISAM→InnoDB)的场景。
- 新老库同时写入(双写),历史数据用脚本分批迁移
- 用
SELECT ... FOR UPDATE或时间戳/版本号机制避免覆盖写冲突 - 迁移完成后,用
pt-table-checksum校验数据一致性,确认无误再切读流量
迁移后关键检查项
别只盯着“导入完成”,这些细节决定是否真正成功:
- 索引重建:如果用
INSERT ... SELECT方式,记得手动ANALYZE TABLE更新统计信息 - 自增ID重置:若目标表是新建的,需
ALTER TABLE t AUTO_INCREMENT = N设为正确起始值 - 权限与字符集:确认用户权限、collation、时区、SQL mode在新库中一致
- 监控延迟与错误日志:观察binlog复制延迟(如用主从)、慢查询日志、Error log是否有报错