上周写了一个存储过程,处理历史数据迁移问题的。
工具 | 数据库版本 | 结果 |
---|---|---|
mysql workbench 8 | 5.6 | 13661条数据只有12976处理了 |
trouble shooting思路:
- 是否是剩下的700多条没提交?(目前是1000条提交一次)
- mysql workbench执行30多秒就会报错,lost connection。是否是这个原因引起的?
- 为什么反复执行都是12976条被处理,是否是第12977条有问题呢?
顺着思路1,楼主原先是在循环体外最终commit一次,现在加上了判断,如果游标到了最后一个结果,则再提交一次。
效果:并没有改善
顺着思路2,对mysql workbench做了配置修改,Edit--->preferences:
效果:lost connection不报错了,但是还是只有12976条数据被处理
顺着思路3,楼主检查了12977条数据,发现并没有问题。一筹莫展之际,楼主注意到了存储过程中的这句话:
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET s=1;
因为存储过程中用到了游标,打开游标后以s<>1作为循环条件来处理。那什么时候发生SQLSTATE ='02000'呢?以下是百度结果:
敲黑板啦。。。。SELECT INTO 语句或 INSERT 语句的子查询的结果为空表。
是的,楼主的存储过程里有select into语句
解决办法:在select into 语句后set s = 0;
这样就可以解决当select into语句子查询的结果为空时退出循环的问题。当然,作为一个完整的存储过程,是需要记录下相关日志信息的,在此不再赘述。
问题解决后,再反过来看当时出现的现象,事实证明,第12977条数据没问题,但是第12976条数据有问题。该条数据在处理过程中遇到select into语句子查询的结果为空,但是程序没有处理这种情况,也没有报错,所以该条数据仍然入库。也误导了楼主的思路3。可见在设计之初,一个健壮的逻辑多么重要。