文章目录
- 背景
- 分析
- 现象
- 排查
- 定位
- 数据比对
- 解决方案
- 反思
背景
背景:今天下午初始化经营体数据到预发环境,需要将生产环境的经营体表的数据同步到预发环境,同步结束后。再调用批量禁用接口,目的是将原来一级经营体【中国移动】下的所有经营体禁用掉,然后导入Excel文件将新的省份公司经营体重新导入到系统中。
使用到的相关表: org_venture 、org_venture_business_configuration 、org_venture_business_type_index_rel、org_venture_employee_relation
分析
这个需求简单可以分三步
- 第一步:将生产环境的上面四张表的数据各自复制一份,发给运维人员。在预发环境上,运维人员会先清空上面四张表的数据,然后再将研发人员提供的四张表的数据导入到数据库里
- 第二步:调用批量禁用接口,目的是将原来一级经营体【中国移动】下的所有经营体都给禁用掉
- 第三步:导入Excel文件将新的省份公司经营体重新导入到系统中
现象
在所有的配置都执行结束后,结果调用getVenturePathByEmpId这个接口报如下错误,getVenturePathByEmpId这个接口的作用是根据人员ID遍历树去查询当前人员对应的经营体的类目链
注意:这里面涉及到遍历树查询,这就为后来的报错埋下祸根
结果就是该接口在pre环境上执行时报堆栈异常错误
排查
思考:这里面只有三个操作步骤,既然这样,那为啥不针对每个步骤逐一去排查问题呢?
步骤1:既然我们的数据是从生产环境上copy下来的,那样的话我们就去生产环境上去查看是否存在数据问题
通过去比对生产环境上的数据,没发现啥问题
思考:那会不会是调用批量禁用接口的时候导致的呢?
步骤2:验证批量禁用接口
结果:没发现任何异常
思考:既然前两个步骤都没有问题,那么会不会是代码的问题?
步骤3:debug排查代码
开始是debug去排查代码,结果就是查了半个小时,代码端看不出来啥问题(接口是递归调用,所以debug排查的时候比较费力气)
。。。
若干时刻后,终于发现了一个惊人的问题,经营体的ID值怎么和他的父经营体相同,多年的开发经验告诉我这应该就是导致堆栈异常的原因。经过深入排查后,最终定位问题就是【id=parent_venture_id】这个问题导致的
定位
导致堆栈异常的问题是找到了,但是它两是怎么相等的,代码问题?还是操作问题?
如果是代码问题:我把全部debug走了一遍,没有发现任何地方设置二者值相同的逻辑
既然不是代码的问题,那应该就是操作的问题了
验证操作问题
首先在生产环境上执行sql: select id, venture_name, parent_venture_id,update_time from org_venture where id = parent_venture_id。没有发现有 【id=parent_venture_id】的数据
那么就去pre环境去排查数据源,结果发现了问题
通过sql: select id, venture_name, parent_venture_id,update_time from org_venture where id = parent_venture_id
发现有好几个经营体的ID和其parent_venture_id相同。
初步结论
- 通过分析代码轻松得知,因为二者相同的缘故导致查询的时候陷入嵌套死循环,由于程序一直执行,自然就把内存资源全部都耗光了,最后报堆栈异常
- 既然是这样的话,那么导致【id=parent_venture_id】数据相同的问题只有两种情况了,要么就是从生产环境上复制数据到pre环境有问题,要么就是Excel导入的新数据有