# Quartz 调度器出现链接超时和 wait_timeout 的问题

# 出现的问题

image-20230605102715494

原因:Mysql 服务器默认的 “wait_timeout” 是 8 小时,也就是说一个 connection 空闲超过 8 个小时,Mysql 将自动断开该 connection。这就是问题的所在,在 C3P0 pools 中的 connections 如果空闲超过 8 小时,Mysql 将其断开,而 C3P0 并不知道该 connection 已经失效,如果这时有 Client 请求 connection,C3P0 将该失效的 Connection 提供给 Client,将会造成上面的异常。

报错信息上提供 autoReconnect=true ,但是在 Mysql 5 之后就已经不再支持了。

# 解决方式

# 修改 quartz 的配置文件

org.quartz.dataSource.qzDS.validationQuery = select 0 from dual
org.quartz.dataSource.qzDS.checkoutTimeout = 10000

# 定时查询数据库

创建新的定时任务来防止 Mysql 自己超时

定时任务:

@SneakyThrows
@Override       
public void execute(JobExecutionContext context) {
    log.info("启动读取任务-----当前时间:{},当前线程:{},当前cron:{}", LocalDateTime.now(), Thread.currentThread().getName(), CRON);
    // ScheduleJob 任务运行时具体参数,可自定义
    log.info("当前时间:{},所有的定时任务是{}", LocalDateTime.now(),QuartzManager.getTotal());
}

定时任务想要随着项目的启动自启动需要注册一下:

@Configuration
public class StartListener implements ApplicationListener<ApplicationStartedEvent> {
    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(StartListener.class);
    private final static String CRON = "0 0 2,7,14,21 * * ? ";
    @Override
    public void onApplicationEvent(ApplicationStartedEvent event) {
        if (QuartzManager.checkExists("startApplicationJob")) {
            logger.info("程序启动,startApplicationJob已存在,时间:{}", LocalDateTime.now());
            QuartzManager.startJobs();
            QuartzManager.removeJob("startApplicationJob", "startApplicationJobGroup", "startApplicationTrigger",
                "startApplicationTriggerGroup");
        } else {
            logger.info("程序启动,开始启动定时任务" + Instant.now());
            QuartzManager.addJob("startApplicationJob", "startApplicationJobGroup", "startApplicationTrigger",
                "startApplicationTriggerGroup", DetectDeviceStatusJob.class, CRON);
        }
    }
}