数据库迁移工具选了半年,最后发现决策的起点错了
前几年做数据库迁移的时候,我一直有个习惯:项目一开始,先研究"怎么迁"。
数据怎么搬,存储过程怎么改,Oracle里的函数到了目标库怎么替换,停机窗口够不够,迁移工具一天能跑多少数据。
后来项目做多了,我才发现这个顺序其实有点问题。
真正容易把项目拖死的,往往不是数据搬不过去,而是项目做到一半,突然发现前面漏算了一堆东西。 
一、一个项目原计划两个月,最后干了四个多月
之前碰到过一个Oracle迁金仓的项目,规模不算小,3000多张表、2000多个存储过程,后面挂着6个应用系统。
项目开始前,我们也做了评估。
当时的方法比较传统,DBA先把源库对象导出来,再人工看视图、函数和存储过程。哪些可以直接迁,哪些可能需要改,先整理成Excel。
几个人忙了差不多三周,最后也确实整理出了一份东西。
问题是,这份东西只能告诉我们"看起来应该差不多"。
真正开始迁以后,各种之前没注意到的问题才陆续冒出来。
有些存储过程调用了比较冷门的Oracle系统包;有些视图套了好几层,单独看每一层SQL都没什么问题,组合起来就不一样了;还有一些函数,名字和用法看起来很普通,到了目标库才发现行为并不完全一致。
最麻烦的是应用里的SQL。
数据库对象至少还能从库里统一导出来,应用SQL散落在Mapper、Java代码、脚本甚至历史版本里。前期没扫全,测试阶段才不断往外蹦。
原来排期两个月,最后做了四个多月。
现在回头看,当时最大的问题其实不是迁移能力不够,而是项目开始的时候,我们根本不知道到底有多少东西需要改。
这两件事差别很大。
二、后来再做迁移,我开始先问一个问题
后面做另外一个DB2迁金仓的项目时,思路换了一下。
这次没有一上来就讨论迁移脚本怎么写,而是先用KDMS把源库扫了一遍。
表、视图、函数、存储过程、触发器这些对象先采集出来,再做兼容性分析。应用侧能收集到的SQL也一起纳入评估。
报告出来以后,我觉得最有用的其实不是那个"兼容率百分之多少"。
真正有价值的是后面的明细。
比如某个存储过程为什么有问题,是语法不支持,还是里面调用了某个目标库不存在的函数;一个SQL需要整体重写,还是只改其中一处;哪些对象基本可以原样迁,哪些应该提前分给开发处理。
以前这些事情要做到迁移中后期才逐渐清楚。
这次是在真正动手之前就看到了大部分。
所以后面的排期就好做很多。DBA负责什么,开发需要改什么,哪些问题风险比较高,都能提前拆出来。
那次前面的方案设计大概用了两周,真正实施迁移反而只用了三周左右。
从那以后,我对"迁移工具"这几个字的理解有点变了。
以前觉得工具最重要的是帮我搬数据、转SQL。
现在反而觉得,迁移前先把问题暴露出来,比迁移过程中帮我自动改掉几个SQL更重要。
三、人工评估最大的问题,不是慢
以前也一直觉得人工评估最大的问题是效率低。
后来发现,慢其实还不是最麻烦的。
麻烦的是它很难稳定。
同样一段SQL,让两个做过不同项目的DBA去看,判断可能不一样。一个人觉得这个函数没问题,另外一个人可能以前踩过坑,会要求提前改。
更别说几千个数据库对象了。
人工检查的时候一定会有优先级。核心表、主要存储过程肯定看得仔细,一些很少执行的触发器、函数、边缘模块,就容易被放到后面。
偏偏迁移项目有时候就是这些东西出问题。
还有一个特别现实的问题:不好估工期。
领导问:
"这个系统迁过去,大概要改多少?"
你很难回答。
最后通常只能说:
"从目前情况来看问题不大,大概两三周。"
做过项目的人应该都知道,"问题不大"和"大概两三周"这两句话有时候挺危险。
因为你并没有真正统计过。
四、KDMS我觉得比较实用的地方,是先把家底摸出来
KDMS整个流程其实没那么复杂。
先在源端采集数据库对象,包括表、视图、约束、序列、函数、存储过程、触发器这些信息。
这里采集的主要是对象定义和结构信息,不是把业务数据整个传上去。
应用侧也可以继续补。
比如项目使用MyBatis,那么Mapper里面的SQL可以扫描;项目目录里的SQL脚本也可以纳入分析。对于运行过程中才动态拼出来的SQL,还可以通过动态采集的方式补充。
这点我觉得比较重要。
因为现在很多迁移项目真正麻烦的已经不只是数据库里的对象了。
数据库里可能只有1000个对象,但应用跑了几年以后,代码里面散落的SQL可能更多。
如果只评估数据库,不评估应用,实际上还是只看了一半。
采集完成以后再上传到KDMS做兼容性分析。
最后出来的东西大致可以理解成一张"迁移体检报告":哪些可以直接处理,哪些需要调整,具体卡在哪里。
到这里,项目经理才真正有东西可以拿来排计划。
五、我一般不会只看那个兼容率
第一次接触这种评估工具,很容易盯着一个数字看:
"兼容率95%,那不是很好迁吗?"
其实未必。
95%的对象兼容,不代表剩下5%很好解决。
如果那5%刚好是几十个核心存储过程,里面又套了大量Oracle特有的系统包,工作量照样可能很大。
所以现在看评估报告,我一般先看不兼容对象是什么,再看数量。
举个很简单的例子。
Oracle里面经常会碰到DECODE、ROWNUM,或者一些特有的系统函数。单独看数量可能很多,但如果替换规则比较明确,实际处理起来并不一定麻烦。
真正需要重点看的,是那些业务逻辑很重、调用关系又复杂的存储过程。
这种东西哪怕只有十几个,也值得单独拉出来评估。
所以我觉得评估工具最大的意义并不是给你一个漂亮的兼容率,而是把原来藏在几千个对象里的问题先筛出来。
人再去处理真正复杂的那部分。
这比让DBA从第一张表开始一直看到最后一个函数靠谱得多。
六、还有一个以前很容易忽略的地方:应用SQL
这个坑我踩过不止一次。
数据库迁完,测试也没什么问题,一上线某个很少使用的功能,SQL报错。
一查发现数据库里根本没有这条SQL。
最后顺着代码找,才发现是某个老模块在Java里面动态拼出来的。
所以现在做迁移,我越来越不赞成只盯着数据库本身。
一个完整的数据库迁移,至少要把三个地方考虑进去:
数据库对象、应用代码里的SQL,以及生产环境真正执行过的SQL。
三部分放在一起看,才比较接近系统真实的使用情况。
KDMS这种"端侧采集+集中评估"的方式,我觉得价值也主要在这里。数据库归DBA,应用归开发,但最后大家看到的是同一份问题清单,而不是各自维护几个Excel。
七、报告出来以后,迁移才算真正开始
评估结束后可以导出报告和对象转换结果,需要修改的SQL也可以继续人工处理、重新校验。
这一点看起来很普通,实际项目里挺有用。
因为迁移从来不可能完全自动化。
特别是大型老系统,里面一定会有一些历史遗留写法,工具没办法百分之百判断业务意图。
这种时候最合理的方式不是强行自动转换,而是工具先把问题定位出来,人来判断怎么改。
例如一个复杂存储过程有800行代码,真正不兼容的可能只有其中三四处。
以前人工检查,相当于先读800行。
现在先告诉你哪几行有问题,再去看上下文,效率完全不一样。
八、我现在做迁移,顺序基本反过来了
以前我的习惯是:
先找迁移工具 → 搬一批数据 → 看报错 → 改问题 → 再迁。
现在更倾向于:
先采集 → 做兼容性评估 → 把问题分类 → 估算改造量 → 排期 → 最后才开始真正迁移。
看起来只是把"评估"提前了一点,实际上对整个项目影响很大。
因为数据库迁移最怕的从来不是遇到问题。
遇到问题很正常。
最怕的是项目已经进行一个月了,突然发现还有一大片问题之前根本没人知道。
如果只是几十张表、几个简单SQL,我觉得没必要搞得这么复杂,DBA人工看看可能更快。
但只要到了几百上千张表,或者系统里有大量函数、触发器、存储过程,再加上几个应用一起迁,前面多花一点时间把家底摸清楚,通常比后面不停救火划算。
做了几次迁移以后,我现在越来越觉得:
数据库迁移真正的第一步,不是把数据搬过去。
而是先搞清楚------这个系统到底有多少东西能直接搬,有多少东西需要改,还有多少坑现在根本没被发现。
这些事情弄清楚以后,真正的数据迁移反而是后面的事了。