这事儿说来也巧,上周一个做金融的老朋友打电话来,说他们公司那个用了快十年的MySQL系统,突然被上面要求迁移到SQL Server。他急得团团转,问我有没有什么坑要避。我听完直接笑了,这哪是什么新鲜事,这几年我见过的数据库迁移案例,少说也有几十个了。从MySQL往SQL Server搬,就跟搬家似的,看着简单,真要动手才发现,光是表结构、数据类型、存储过程这些细碎的地方,就能让你头疼好几天。

先说数据类型这块吧。MySQL里用的TINYINT,到SQL Server里虽然也有,但逻辑上有个细微差别:MySQL里TINYINT(1)经常被用来表示布尔值,0和1,但SQL Server的TINYINT范围是0到255,你如果直接把字段搬过去,程序里还在做布尔判断,那就等着出bug吧。更麻烦的是DATETIME,MySQL的DATETIME范围是1000年到99年,SQL Server的却是1753年起步,你要是表里存了历史数据,比如“公元800年”,那迁移时直接就报错。还有那个烦人的ENUM类型,MySQL里用得挺顺手,到SQL Server里压根不认,你得自己改成VARCHAR或者加CHECK约束。这些细节,光靠工具自动转换,十有八九会出幺蛾子。
再说存储过程和函数。MySQL和SQL Server的语法差异,简直就是两种语言。比如变量声明,MySQL用DECLARE,SQL Server也差不多,但赋值方式一个用SET,一个用SELECT,容易混。更头疼的是游标和异常处理,MySQL的DECLARE CONTINUE HANDLER,到SQL Server里得换成TRY...CATCH,逻辑上得重新捋一遍。我见过一个项目,客户把几百个存储过程直接扔给迁移工具,跑完之后发现一半跑不出来,人工改了一个月。所以我的建议是:迁移之前,先把所有存储过程、函数、触发器的代码过一遍,该重写的重写,别指望自动化工具能帮你搞定一切。工具只能帮你搬砖,砌墙还得自己来。
还有字符串和排序规则这事儿,也容易翻车。MySQL默认的utf8mb4和SQL Server的Latin1_General,处理中文时表现完全不同。你可能在MySQL里查“张三”和“张叁”没问题,到了SQL Server里,排序规则没配好,直接给你当成两个不同的字。而且大小写敏感也是个雷,MySQL默认大小写不敏感,SQL Server默认却是大小写敏感。你要是原来有个表叫users,另一个叫Users,在MySQL里没问题,到SQL Server里直接就冲突了。这种问题,迁移前就得统一规范,要么全部小写,要么全部大写,别留尾巴。
当然了,说到迁移,就绕不开数据量和效率。我见过最夸张的一个案例,是某电商公司要迁移一亿多条订单数据,直接用INSERT INTO...SELECT,结果跑了三天三夜还没跑完。后来改成批量提交,每批一万条,配合事务和索引禁用,两天就搞定了。还有索引重建的问题,SQL Server的索引策略和MySQL不太一样,搬完数据之后,别忘了重新评估索引设计。原来在MySQL里好用的复合索引,到了SQL Server里可能根本用不上,得根据查询计划重新调整。这个步骤要是省了,上线之后性能可能比原来还差。
说说工具选择。市面上有很多迁移工具,比如微软官方的SQL Server Migration Assistant for MySQL,还有第三方的Navicat、DBConvert。我的经验是:工具可以帮你省掉80%的重复劳动,但剩下20%的精细活,必须人工介入。尤其是数据验证这一步,迁移完之后,一定要对比源库和目标库的行数、关键字段的值、约束是否完整。我见过有人用工具跑完就上线,结果发现少了几万条数据,排查了两天才找到原因——工具在处理某些特殊字符时直接跳过了。所以别偷懒,写个脚本做全量对比,安全第一。
说到底,数据库迁移这事儿,看着是技术活,其实更是管理活。你得把节奏控制好,分阶段来做:先做数据结构和存储过程的转换,再做数据迁移,然后做功能测试和性能调优,最后才是上线切换。每个阶段都要有回滚方案,别一条路走到黑。我那朋友听完,沉默了几秒,说“那我先让团队把存储过程过一遍吧”。我知道,他算是听进去了。毕竟在这个行业里混久了,谁还没为迁移踩过几个坑呢。


