今天早上dba群里抛出一个问题说,有一个长事务一直在重复执行我们的一个语句。于是问题抛给我们,我们开始排查。
首先dba告知我们这句sql是重复在调用,然后还有这个事务的其他sql语句,还有开始的时间点。
我的想法是先从请求入手,看看这个时间点有没有耗时特别长的,或者跟这些sql相关的请求,但是一开始并没有找到,原因后面再说。
第一步失败后,就只能从代码找起了,先找到对应sql的位置,然后找到对应的接口,一步步找。这个过程是比较痛苦的,还好我运气不错,找到了跟这个长事务中的sql十分相似的代码,是订单导出。
原本这个导出是不加事务的,但是后面出现了一个问题,就是当导出数据量很大的时候,会采取分批导出,分批获取订单数据时,会出现重复或者漏单的情况(如果中途有数据更新),为了防止这个问题,我们同事在导出方法上加了不可重复读的事务注解。
这样虽然解决了上面的问题(其他事务的更新不会影响到本事务),但是与此同时,因为导出数据太多,耗时很长,所以这样改后就会出现一个长事务,长期占用数据库连接资源,可能会出现连接耗尽的风险。
为什么一开始查请求没有排查到呢,首先订单导出不是我们组负责的,所以对这块的代码也不熟悉,其次因为我们导出都是通过异步的方法执行的,所以从请求耗时上也没有查出异样。
解决方法是可以把每次分批把最大的数据记录下来,下次分批需要查询大于这条记录的数据来分页,这样可以避免重复和漏单的问题