咋整,定时任务不执行了! | Java Debug 笔记

823 阅读2分钟

**本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看活动链接 **

一 事故背景

故事要从接到一个产品的朦胧需求开始,那一次产品提了一个需求,要求每天凌晨1点,对系统里面的未确认的收款数据,进行收款确认,核销,挂账操作,听起来也许很简单,如下图

graph TD
定时器查询配置项 
--> 遍历配置项
--> 根据配置项查出要进行处理的数据
--> 对数据进行收款确认
--> 核销处理
--> 挂账处理
--> 处理成功的数据写入日志表 

大概就是这样。但是业务复杂度极高,因为你不知道收款确认有哪些校验,核销是啥逻辑,挂账又是啥逻辑,于是就出现了开发看代码,发现问题通知产品,产品增加需求,开发接到新的需求接着改,唉,感觉是不是开发在做产品的工作。

二 事故现场

有时候最担心的就是你做的需求,需求自己都不太了解,但就是这种情况下,产品就是坚持一定要上线,出了问题,对不起了开发大兄弟,要开始你的表演了。 在经历一些小问题后,突然之间出现了一个问题,本应该凌晨执行的定时器不跑了。

image.png

产品第一时间通知开发,咋回事呢,怎么不跑了,那么第一时间开发就去看了Kibana上面的日志,发现一共配置了12条数据,但是跑到第8条不跑了,然后查看整个流程,最终发现一条sql执行的特别慢,于是定位到这段代码

 /**
     * 查询需要自动确认数据
     * 业务类型 0 进口 1出口 2报关 3船务
     *
     * @param orgGroupCode
     * @param businessType
     * @param paymentType
     * @param proceedsDate
     * @return
     */
    @Query(value = "select * from rp_freight where ORG_GROUP_CODE = :orgGroupCode and  BUSINESS_TYPE = :businessType " +
            "and PAYMENT_TYPE =:paymentType and GATHERING_STATUS = 1 and CONFIRM_STATUS != 1" +
            "and to_char(GATHERING_TIME,'yyyy-MM-dd') = :proceedsDate and arap='R' ", nativeQuery = true)
    List<RpFreight> getAutoConfirmRpFreight(@Param("orgGroupCode") String orgGroupCode,
                     @Param("businessType") Integer businessType,
                     @Param("paymentType") Integer paymentType,
                     @Param("proceedsDate") String proceedsDate);
                     

这条代码对应的sql在执行第8个配置项时,因为第8个配置项的数据量很大,sql执行了4分多钟,最终导致了线程的假死,程序不向后执行。 我们进一步,看一下他为什么这么慢,仔细看,这里使用了一个函数来转换时间

 to_char(GATHERING_TIME,'yyyy-MM-dd') = :proceedsDate 

使用函数来转换字段是不回走索引的,于是就导致了全表扫描,悲剧就这样造成了。

三 解决方案

去掉函数,改为传入开始,结束时间,问题解决

   @Query(value = "select * from rp_freight where ORG_GROUP_CODE = :orgGroupCode and  BUSINESS_TYPE = :businessType " +
            "and PAYMENT_TYPE =:paymentType and COMMITMENT =:commitment and GATHERING_STATUS = 1 and CONFIRM_STATUS != 1" +
            "and GATHERING_TIME >= :getYesterBeginTime and GATHERING_TIME <= :getYesterEndTime and arap='R' ", nativeQuery = true)
    List<RpFreight> getAutoConfirmRpFreightCm(@Param("orgGroupCode") String orgGroupCode,
                                            @Param("businessType") Integer businessType,
                                            @Param("paymentType") Integer paymentType,
                                            @Param("commitment") String commitment,
                                            @Param("getYesterBeginTime") Date getYesterBeginTime,
                                            @Param("getYesterEndTime") Date getYesterEndTime );