最近有个朋友跟我吐槽,他们公司要把一套跑了五年的 MySQL 数据库从阿里云迁移到腾讯云。本以为就是导出导入的活儿,结果折腾了两周还没搞定。我听完就乐了,这事儿我太熟了。数据库迁移表面上看是数据搬家,实际上是系统工程,稍不留神就能让你加班到怀疑人生。很多技术负责人一开始觉得很简单,不就是 mysqldump 倒一下再导入新库吗?但真动手时才发现,版本差异、字符集乱码、存储过程兼容性、主键冲突、外键约束、权限丢失、索引失效,这些问题一个接一个冒出来。更别提那些跑在生产环境的在线业务,你这边一停服,老板的电话就追了过来。

说到具体的迁移方案,其实要看业务的容忍度。如果允许停机几小时,最稳妥的办法就是用 mysqldump 全量导出,配合 --single-transaction 参数保证数据一致性。但如果像电商平台那样,凌晨三点还有人下单,就得用更高级的工具。我见过不少团队使用 Percona XtraBackup 做物理备份,这个工具好在它能在不锁表的情况下备份 InnoDB 表,速度比逻辑备份快得多。还有个叫 gh‑ost 的工具,是 GitHub 开源的在线 DDL 工具,也能辅助迁移。不过说实话,工具选得好是锦上添花,真正决定成败的是你对数据量的预判和对业务的理解。我曾见过有人用 mysqldump 导一个 2 TB 的库,结果跑了十几个小时还没完,中途网络断了,前功尽弃。
数据迁移中最容易翻车的,就是字符集和排序规则的问题。很多老项目建库时用的是 latin1,后来业务发展,数据里混进了中文、表情符号,但字符集一直没改。搬数据时如果不做转换,导入到新库的 utf8mb4 上就会报错或出现乱码。我有个前同事就栽在这上面,迁移完才发现用户昵称里的 emoji 全变成了问号,被运营追着骂了一个星期。更坑的是,有些表的默认字符集和字段的字符集不一致,你光改库的字符集没用,得逐个字段检查。建议在迁移前先跑一遍 SHOW CREATE TABLE,把所有建表语句都看一遍,把字符集和排序规则统一成 utf8mb4 和 utf8mb4unicodeci,这样至少能避免 80% 的字符集问题。
除了字符集,索引和主键的设计也常在迁移后暴雷。我见过一个案例,某表在旧库上用了自增主键,迁移到新库后因为导入顺序不同,导致主键值不连续,结果应用层有个缓存逻辑依赖主键自增规律,直接崩了。更隐蔽的问题是:旧库的某些索引是冗余的,比如有个联合索引 (a, b),又单独建了索引 (a)。在新库上其实可以合并,但如果机械复制 DDL,就会把冗余带过去,浪费磁盘空间并拖慢写入性能。迁移是个绝佳时机,应该趁机重构不合理的设计。比如把低频查询的大表拆成小表,把 JSON 字段拆成关系表,把过长的索引字段缩短。千万别想着“先迁过去再说”,等上线后再改,代价会更大。
权限管理也是迁移中的雷区。MySQL 的权限是跟主机名绑定的,你从阿里云迁到腾讯云,IP 地址变了,原来 grant 语句里写的 ‘user’@‘10.0.0.%’ 就全失效。更麻烦的是,有些应用的连接池配置里写死了旧库 IP,迁移完忘了通知运维改配置,结果应用仍往旧库写数据,两边数据不一致,排查起来会让人崩溃。建议迁移前先导出完整的权限列表,pt-show-grants 能做到。然后在新库上重新授权,注意把主机名改成新的网段或直接用 ‘%’。同时清理无用的账号,比如开发人员的测试账号,旧库上可能有几十个,迁过去全是安全隐患。
数据迁移完后,验证环节才是真正考验耐心的时候。很多人觉得把数据导进去就完事了,结果上线第一天就发现某个报表的金额对不上。我的做法是迁移完成后先跑校验脚本,对比旧库和新库的行数、checksum 值。对关键表,我会随机抽几条记录的某个字段,用 MD5 比对。更稳妥的办法是使用 pt‑table‑checksum,它能逐行比对主键,把不一致的数据找出来。但要注意,这个工具会消耗数据库资源,尽量在业务低峰期运行。另外,别忘了检查视图、存储过程、触发器和事件,这些对象在迁移过程中经常因为依赖关系处理不当而漏掉。我见过最离谱的情况是,有人把数据迁完了,却忘了迁移定时任务,结果第二天凌晨该跑的报表没跑,业务直接停摆。
聊几句回滚方案的事。很多人做迁移时只想把数据搬过去,根本没考虑万一失败怎么办。现实是,迁移失败的概率比想象的高。网络抖动、磁盘空间不足、版本不兼容、内存溢出,任何一个环节出问题,都可能导致必须回滚。所以动工前一定要保留旧库,别急着销毁。最好在旧库上创建只读副本,万一新库出问题还能切回。回滚流程也要提前演练一遍,别到时候手忙脚乱。我有一次血的教训:迁移完成后以为万事大吉,就把旧库备份删了。结果新库上线后,一个存储过程的逻辑有 bug,导致数据写错,想回滚却没有备份,只能靠业务日志手工修复,熬了两个通宵。
说到底,MySQL 数据库迁移本身并不复杂,真正难的是对细节的把控和对意外的预判。把字符集、权限、索引、回滚这些坑都提前填好,迁移就是按部就班的事。但如果心存侥幸,觉得“应该没问题”,大概率就会出问题。我见过太多技术负责人,平时技术很牛,却在迁移这种实操性强的事情上栽跟头,原因就是太自信、太粗糙。数据库是业务的命根子,动它之前多花两天时间做方案、做测试、做演练,比上线后再花两周救火要划算得多。记住:迁移不是技术表演,而是风险控制。


