讲到SP,那真是痛苦中的痛苦啊,调试困难,测试困难;因为它不仅受到本身代码准确性的影响,也受到被执行数据的正确性、数据量、数据库特性等的诸多影响,所以在数据库迁移的过程中复杂SP改写和测试就是重中之重了。
很有幸,最近工作中碰到了一次大规模的数据库迁移测试,虽然耗掉了半条老命,但总算项目成功收尾,总算也有些闲暇来写点总结感受。
开始,单步调试和程序调试一样,单步的调试肯定是最有效的,所以单步执行存储过程中的逻辑是基础。橙子也是这么做的,橙子挑取了部分测试数据,小数据量的,只为验证逻辑。将Update操作改写为Select,因为Update操作比较耗费资源,并且破坏原数据。为了测试效率,橙子需要尽快知道逻辑正确性,不过这个也为后续的测试错误埋下了伏笔。
臭虫,MySQL的表别名单步调试开始,第一段逻辑就发现了BUG。由于项目是从SqlServer迁移至Mysql,SqlServer对于表别名是不区分大小写的,而Mysql则区分大小写,结果造成了表别名书写的大量错误。上百个复杂SP,发动程序,DBA一起修改,也算是顺利修改完成,测试继续
麻烦,数据导入错误橙子继续测试,但总是逻辑错误,代码Review之后,确定应该是数据问题,随后开始检查数据。这下傻眼了,发现从SqlServer迁移过来的数据有大量错误,主要是datetime,bit这类。随后查原因,原来SqlServer中有默认值的字段,到MySQL后由于没有默认值,都成了null了;而使用文本导出导入的方式,又将SqlServer中大量的空字段转变成了/0。这下DBA也傻眼了,重做数据吧。之后橙子提议,在导出数据后要做必要的Check,以确保导入。这里也给橙子自己一个提醒,测试开始前应先确保被测数据的正确性,这样更方便Cause的确定
注意,MySQL不会自动取整解决了数据问题,橙子又发现了一个Bug,原来SqlServer在除运算后是会自动取整的,但是Mysql不会。如果你在除运算后,有case操作,那就要特别注意了。小数据量的单步调式顺利完成,橙子和同事们都对本次迁移充满信心,因为复杂逻辑没有问题,SP的集成调用也OK,事先最担心的逻辑验证看来很顺利。事实证明麻烦真的就是会在你盲目乐观的时候找上门的。
狗屎,MySQL的查询优化随后导入了海量数据,开始仿真测试。也许SqlServer还算可以的查询优化,把我们的程序员和DBA都养懒了。大段大段的子查询,大量的join操作迁移到MySQL后,原先几10秒完成的Select,10分钟都完成不了。看来MySQL的查询优化还真是不行。这下麻烦了,连测试结果都得不到,咋整?没辙,大家打回原始社会吧,工具不行,只能靠人了。于是开始解耦,靠人来优化查询。最后我们花了大量的时间,使用内存零时表的方式,解耦了大部分join查询,使SP中的每个Select都尽量简单,也算人为解决了查询优化的问题。
这个过程耗费了整个迁移工作量的绝大部分,并且导致了所有逻辑测试必须返工重做。因此橙子对于之前没有预估海量数据和查询优化造成的影响而急功近利的做法懊悔不已。
未完待续