一、Quartz的基本概念
核心概念
Job 表示一个工作,要执行的具体内容。此接口中只有一个方法,void execute(JobExecutionContext context)
JobDetail 表示一个具体的可执行的调度程序,Job 是这个可执行程调度程序所要执行的内容,另外 JobDetail 还包含了这个任务调度的方案和策略。
Trigger 触发器,指定何时触发任务。
Scheduler 代表一个调度容器,一个调度容器中可以注册多个 JobDetail 和 Trigger。当 Trigger 与 JobDetail 组合,就可以被 Scheduler 容器调度了。
Quartz集群架构
一个Quartz集群中的每个节点是一个独立的Quartz应用,它又管理着其他的节点。这就意味着你必须对每个节点分别启动或停止。Quartz集群中,独立的Quartz节点并不与另一其的节点或是管理节点通信,而是通过相同的数据库表来感知到另一Quartz应用的。
二、Spring Boot整合Quartz
Spring Boot2.x中提供了对Quartz的自动配置,并纳入了Spring容器中进行管理。
pom:
<!--quartz依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<!--quartz依赖-->
数据库持久化表:
官网下载quartz jar包\docs\dbTables下。
文章结尾附带MySQL Quartz脚本
注意:Quartz中是通过sched_name、job_name 和 job_group来确定Job的唯一性的
yml:
spring:
quartz:
#相关属性配置
properties:
org:
quartz:
scheduler:
instanceName: clusteredScheduler
instanceId: AUTO
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
tablePrefix: QRTZ_
#集群设置
isClustered: true
clusterCheckinInterval: 10000
useProperties: true
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 10
threadPriority: 5
#设置守护线程 默认为true
threadsInheritContextClassLoaderOfInitializingThread: true
#数据库方式
job-store-type: jdbc
#初始化表结构
#jdbc:
#initialize-schema: never
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/security?useUnicode=true&characterEncoding=utf8
username: root
password: root
application:
name: quartz-node-one
如果需要对Quartz的SchedulerFactoryBean进行配置,可以实现SchedulerFactoryBeanCustomizer来实现
Job:
继承QuartzJobBean,重写executeInternal方法,实现自己的业务逻辑。Job中可以直接注入Spring容器管理的Bean,如service
@Slf4j //此处为lomback注解 生成log对象
public class TestJob extends QuartzJobBean {
@Autowired
private UserService userService;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info(userService.toString());
log.info("执行定时任务------------"+System.currentTimeMillis());
}
}
到此,整合完毕,下面接着写页面管理job。
注意:现在这个job是不完整的,因为没有配置jobdetil内容,我们将在后面的页面管理中进行配置
三、页面化管理
自定义表
注意:这张表和前面官网的表没有任何关系,和quartz的定时任务执行严格的讲也没有任何关系。这张表只是存储我们通过
页面定义的一些job信息,然后再通过quartz的api将这些job放到quartz的持久化数据库中,也就是前面建的表中。
quartz的任务调度用的是官网提供sql脚本中初始化的表,而不是我们现在自定义的表。
//这个表可自行定义
CREATE TABLE `sys_job` (
`job_id` varchar(64) NOT NULL,
`job_name` varchar(64) DEFAULT NULL,
`job_group` varchar(64) DEFAULT NULL,
`cron_expression` varchar(64) DEFAULT NULL,
`job_status` varchar(64) DEFAULT NULL,
`job_class` varchar(200) DEFAULT NULL,
`prevfire_time` date DEFAULT NULL,
PRIMARY KEY (`job_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
自定义:QuartzManager类
这个类可以直接当做工具类使用,包含了job的新增、删除、修改、暂停、重启、开启所有job、关闭所有job等方法
import com.txp.boot.quartz.model.entity.SysJob;
import lombok.extern.slf4j.Slf4j;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.Trigger.TriggerState;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
//让Spring管理这个Bean
@Component
@Slf4j
public class QuartzManager {
//注入调度器
@Autowired
private Scheduler scheduler;
/**
* @Description: 添加一个定时任务,使用默认的任务组名,触发器名,触发器组名
*
* @param myJob
*
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public void addJob(SysJob myJob, Class cls) {
log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>method:addJob start");
try {
// 唯一主键
String jobName = myJob.getJobName();
String jobGroup = myJob.getJobGroup();
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
if(scheduler==null){ log.info("scheduler is null");}
CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
if (null == cronTrigger) {
JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(jobName,jobGroup).build();
cronTrigger = TriggerBuilder.newTrigger().withIdentity(jobName, jobGroup)
.withSchedule(CronScheduleBuilder.cronSchedule(myJob.getCronExpression())).build();
// cronTrigger.getJobDataMap().put("jobEntity", myJob);
scheduler.scheduleJob(jobDetail, cronTrigger);
//启动一个定时器
if (!scheduler.isShutdown()) {
scheduler.start();
}
} else {
cronTrigger = cronTrigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(CronScheduleBuilder.cronSchedule(myJob.getCronExpression()))
.build();
scheduler.rescheduleJob(triggerKey, cronTrigger);
}
//等待启动完成
// Thread.sleep(TimeUnit.SECONDS.toMillis(10));
} catch (Exception e) {
e.printStackTrace();
log.info("定时任务启动失败:" + e.getMessage());
}
log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>method:addJob end");
}
/**
* @Description: 暂停一个任务
*
* @param myJob
*
*/
public void pasueOneJob(SysJob myJob) {
log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>method:pasueOneJob start");
try {
// 唯一主键
String jobName = myJob.getJobName();
String jobGroup = myJob.getJobGroup();
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
Trigger trigger = scheduler.getTrigger(triggerKey);
// if(null==trigger){
// log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>method:removeJob trigger is NULL ");
// return;
// }
JobKey jobKey = trigger.getJobKey();
scheduler.pauseJob(jobKey);
} catch (Exception e) {
throw new RuntimeException(e);
}
log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>method:pasueOneJob end");
}
/**
* @Description: 重启一个任务
*
* @param myJob
*
*/
public void resOneJob(SysJob myJob) {
log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>method:resOneJob start");
try {
// 唯一主键
String jobName = myJob.getJobName();
String jobGroup = myJob.getJobGroup();
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
Trigger trigger = scheduler.getTrigger(triggerKey);
// if(null==trigger){
// log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>method:removeJob trigger is NULL ");
// return;
// }
scheduler.rescheduleJob(triggerKey, trigger);
// Thread.sleep(TimeUnit.MINUTES.toMillis(10));
} catch (Exception e) {
throw new RuntimeException(e);
}
log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>method:resOneJob end");
}
/**
* @Description: 修改一个任务的触发时间
*
*/
public void modifyJobTime(SysJob myJob, String time) {
log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>method:modifyJobTime start");
try {
// 唯一主键
String jobName = myJob.getJobName();
String jobGroup = myJob.getJobGroup();
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);
myJob.setCronExpression(time);
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(myJob.getCronExpression());
cronTrigger = cronTrigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(cronScheduleBuilder)
.build();
scheduler.rescheduleJob(triggerKey, cronTrigger);
// Thread.sleep(TimeUnit.MINUTES.toMillis(60));
} catch (Exception e) {
throw new RuntimeException(e);
}
log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>method:modifyJobTime end");
}
/**
* @Description: 移除一个任务(使用默认的任务组名,触发器名,触发器组名)
*
*
*/
public void removeJob(SysJob myJob) {
log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>method:removeJob start");
try {
// 唯一主键
String jobName = myJob.getJobName();
String jobGroup = myJob.getJobGroup();
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
Trigger trigger = scheduler.getTrigger(triggerKey);
if(null==trigger){
log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>method:removeJob trigger is NULL ");
return;
}
JobKey jobKey = trigger.getJobKey();
scheduler.pauseTrigger(triggerKey);// 停止触发器
scheduler.unscheduleJob(triggerKey);// 移除触发器
scheduler.deleteJob(jobKey);// 删除任务
//Thread.sleep(TimeUnit.MINUTES.toMillis(10));
} catch (Exception e) {
throw new RuntimeException(e);
}
log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>method:removeJob end");
}
/**
*
* 方法表述 获得执行器状态
* @return
* String
*/
public String getStatus(SysJob myJob){
String state = "NONE";
try {
// 唯一主键
String jobName = myJob.getJobName();
String jobGroup = myJob.getJobGroup();
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
//trigger state
TriggerState triggerState = scheduler.getTriggerState(triggerKey);
state = triggerState.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
return state;
}
/**
* 是否存在任务
* 方法表述
* @param myJob
* @return
* boolean
*/
public boolean hasTrigger(SysJob myJob){
boolean isHas = true;
try {
// 唯一主键
String jobName = myJob.getJobName();
String jobGroup = myJob.getJobGroup();
TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
Trigger trigger = scheduler.getTrigger(triggerKey);
if(null==trigger){
log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>method:removeJob trigger is NULL ");
isHas = false;
}
} catch (SchedulerException e) {
isHas = false;
e.printStackTrace();
}
return isHas;
}
/**
* @Description:启动所有定时任务
*
*/
public void startJobs() {
try {
scheduler.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* @Description:关闭所有定时任务
*
*/
public void shutdownJobs() {
try {
if (!scheduler.isShutdown()) {
scheduler.shutdown();
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
Controller层
controller中,可以直接注入我们前面定义的QuartzManager类
@Slf4j
@RestController
@RequestMapping("/sysJob")
public class SysJobController {
//自动注入QuartzManager
@Autowired
private QuartzManager quartzManager;
@Resource
private SysJobService jobService;
/**
* 页面访问方法的定义,这里是一个修改job的方法,具体逻辑自行定义
* 1.此处为省事,没有返回值
* 2.quartzManager.removeJob(t) 调用Quartz Api 从Quartz持久化的表中移除任务
* 3.jobService.updJob(job) 调用自定义的service 对自定义表sys_job进行更新操作
* 4.此处注释只是为了强调,页面化管理job只是管理自己创建表中job,想要更改Quartz持久化表中的Job,
必须调用Quartz的Api
*/
@PostMapping("editJob")
public void editJob(SysJob job){
try {
if(job.getJobId()!=null && StringUtils.isNotBlank(job.getJobId().toString())){
SysJob t = jobService.queryById(job.getJobId());
if(null != t){
quartzManager.removeJob(t);
}
jobService.updJob(job);
log.info("成功","修改成功");
}else{
job.setJobId(ToolsUtils.generatorUUID());
jobService.addJob(job);
log.info("成功","创建成功");
}
//新增或者重新添加job
quartzManager.addJob(job,Class.forName(job.getJobClass()));
} catch (Exception e) {
log.info("失败","修改失败");
}
}
}
Service/Dao层
笔者用的是mybatis-plus做的数据层访问,基础的增删改查,这里不再粘贴代码
MockMvc测试
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
@RunWith(SpringRunner.class)
@SpringBootTest
public class QuartzDemoApplicationTest {
/**
* 模拟mvc测试对象
*/
private MockMvc mockMvc;
/**
* web项目上下文
*/
@Autowired
private WebApplicationContext webApplicationContext;
/**
* 所有测试方法执行之前执行该方法
*/
@Before
public void before() {
//获取mockmvc对象实例
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
/**
* 测试通过web添加一个job,这里调用的是editjob接口
* @throws Exception
*/
@Test
public void addGood() throws Exception
{
MvcResult result = mockMvc.perform(MockMvcRequestBuilders.post("/sysJob/editJob")
.param("jobName","job_test")
.param("jobGroup","tes_group")
.param("jobStatus","1")
.param("jobClass","com.txp.boot.quartz.timers.job.TestJob")
.param("cronExpression","0/5 * * * * ?")
)
.andDo(MockMvcResultHandlers.print())
.andExpect(MockMvcResultMatchers.status().is(200))
.andReturn();
result.getResponse().setCharacterEncoding("UTF-8");
System.out.println(result.getResponse().getContentAsString());
}
}
代码运行步骤:
1.先运行测试类,添加一个job
2.启动Spring主启动类,就可以在控制台看到定时任务的执行了
以上就是spring boot整合Quartz 并实现页面化控制的一个demo,如有错误或者不足,还请指正。再啰嗦一句,页面化控制是操作的我们自己定义的job表,实际操作Quartz还是调用Quartz的类库。
MySQL 数据库脚本
DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS;
CREATE TABLE QRTZ_JOB_DETAILS(
SCHED_NAME VARCHAR(120) NOT NULL,
JOB_NAME VARCHAR(190) NOT NULL,
JOB_GROUP VARCHAR(190) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
JOB_CLASS_NAME VARCHAR(250) NOT NULL,
IS_DURABLE VARCHAR(1) NOT NULL,
IS_NONCONCURRENT VARCHAR(1) NOT NULL,
IS_UPDATE_DATA VARCHAR(1) NOT NULL,
REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
JOB_NAME VARCHAR(190) NOT NULL,
JOB_GROUP VARCHAR(190) NOT NULL,
DESCRIPTION VARCHAR(250) NULL,
NEXT_FIRE_TIME BIGINT(13) NULL,
PREV_FIRE_TIME BIGINT(13) NULL,
PRIORITY INTEGER NULL,
TRIGGER_STATE VARCHAR(16) NOT NULL,
TRIGGER_TYPE VARCHAR(8) NOT NULL,
START_TIME BIGINT(13) NOT NULL,
END_TIME BIGINT(13) NULL,
CALENDAR_NAME VARCHAR(190) NULL,
MISFIRE_INSTR SMALLINT(2) NULL,
JOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
REPEAT_COUNT BIGINT(7) NOT NULL,
REPEAT_INTERVAL BIGINT(12) NOT NULL,
TIMES_TRIGGERED BIGINT(10) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_CRON_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
CRON_EXPRESSION VARCHAR(120) NOT NULL,
TIME_ZONE_ID VARCHAR(80),
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_SIMPROP_TRIGGERS
(
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
STR_PROP_1 VARCHAR(512) NULL,
STR_PROP_2 VARCHAR(512) NULL,
STR_PROP_3 VARCHAR(512) NULL,
INT_PROP_1 INT NULL,
INT_PROP_2 INT NULL,
LONG_PROP_1 BIGINT NULL,
LONG_PROP_2 BIGINT NULL,
DEC_PROP_1 NUMERIC(13,4) NULL,
DEC_PROP_2 NUMERIC(13,4) NULL,
BOOL_PROP_1 VARCHAR(1) NULL,
BOOL_PROP_2 VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_BLOB_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
BLOB_DATA BLOB NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_CALENDARS (
SCHED_NAME VARCHAR(120) NOT NULL,
CALENDAR_NAME VARCHAR(190) NOT NULL,
CALENDAR BLOB NOT NULL,
PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
ENGINE=InnoDB;
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
ENGINE=InnoDB;
CREATE TABLE QRTZ_FIRED_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
ENTRY_ID VARCHAR(95) NOT NULL,
TRIGGER_NAME VARCHAR(190) NOT NULL,
TRIGGER_GROUP VARCHAR(190) NOT NULL,
INSTANCE_NAME VARCHAR(190) NOT NULL,
FIRED_TIME BIGINT(13) NOT NULL,
SCHED_TIME BIGINT(13) NOT NULL,
PRIORITY INTEGER NOT NULL,
STATE VARCHAR(16) NOT NULL,
JOB_NAME VARCHAR(190) NULL,
JOB_GROUP VARCHAR(190) NULL,
IS_NONCONCURRENT VARCHAR(1) NULL,
REQUESTS_RECOVERY VARCHAR(1) NULL,
PRIMARY KEY (SCHED_NAME,ENTRY_ID))
ENGINE=InnoDB;
CREATE TABLE QRTZ_SCHEDULER_STATE (
SCHED_NAME VARCHAR(120) NOT NULL,
INSTANCE_NAME VARCHAR(190) NOT NULL,
LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
CHECKIN_INTERVAL BIGINT(13) NOT NULL,
PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
ENGINE=InnoDB;
CREATE TABLE QRTZ_LOCKS (
SCHED_NAME VARCHAR(120) NOT NULL,
LOCK_NAME VARCHAR(40) NOT NULL,
PRIMARY KEY (SCHED_NAME,LOCK_NAME))
ENGINE=InnoDB;
CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
commit;