Quartz database table analysis

Foreword
The previous article Spring integrates Quartz distributed scheduling and introduced that Quartz implements distributed scheduling through the database. By using the database to store triggers, jobs and other information, the state of the last trigger can be reloaded when the server is stopped and restarted. Integrity is guaranteed; on the other hand, the lock mechanism is implemented through the database to achieve distributed scheduling; Quartz provides 11 tables by default, and this article will briefly analyze these tables.

table information

1.qrtz_blob_triggers
2.qrtz_cron_triggers
3.qrtz_simple_triggers
4.qrtz_simprop_triggers
5.qrtz_fired_triggers
6.qrtz_triggers
7.qrtz_job_details
8.qrtz_calendars
9.qrtz_paused_trigger_grps
10.qrtz_scheduler_state
11.qrtz_locks

There are 11 tables in total, the first 6 are information about various triggers, followed by job, pessimistic lock, scheduling status and other information; related table operations are in class StdJDBCDelegate, and related sql statements are in StdJDBCConstants;

1. The custom triggers of qrtz_blob_triggers
are stored in the blog type. Non-custom triggers will not be stored in this table. The triggers provided by Quartz include: CronTrigger, CalendarIntervalTrigger,
DailyTimeIntervalTrigger and SimpleTrigger. These trigger information will be saved in the following in several tables;

2. qrtz_cron_triggers
stores CronTrigger, which is also the trigger we use the most. Do the following configuration in the configuration file to generate records in qrtz_cron_triggers:

<bean id="firstCronTrigger"
    class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
    <property name="jobDetail" ref="firstTask" />
    <property name="cronExpression" value="0/6 * * ? * *" />
    <property name="group" value="firstCronGroup"></property>
</bean>
<bean id="firstTask"
    class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
    <property name="jobClass" value="zh.maven.SQuartz.task.FirstTask" />
    <property name="jobDataMap">
        <map>
            <entry key="firstService" value-ref="firstService" />
        </map>
    </property>
</bean>
<bean id="firstService" class="zh.maven.SQuartz.service.FirstService"></bean>

The expression specifies the execution every 6 seconds, and then specifies the task to be executed. The task specifies the business to be executed. After running, you can view the data table:

mysql> select * from qrtz_cron_triggers;
+-------------+------------------+----------------+-----------------+---------------+
| SCHED_NAME  | TRIGGER_NAME     | TRIGGER_GROUP  | CRON_EXPRESSION | TIME_ZONE_ID  |
+-------------+------------------+----------------+-----------------+---------------+
| myScheduler | firstCronTrigger | firstCronGroup | 0/6 * * ? * *   | Asia/Shanghai |
+-------------+------------------+----------------+-----------------+---------------+

myScheduler is the name specified when the SchedulerFactoryBean is defined, other fields can be found in the above configuration;

3. qrtz_simple_triggers
store SimpleTrigger, do the following configuration in the configuration file, you can generate records in qrtz_simple_triggers:

<bean id="firstSimpleTrigger"
    class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
    <property name="jobDetail" ref="firstSimpleTask" />
    <property name="startDelay" value="1000" />
    <property name="repeatInterval" value="2000" />
    <property name="repeatCount" value="5"></property>
    <property name="group" value="firstSimpleGroup"></property>
</bean>
<bean id="firstSimpleTask"
    class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
    <property name="jobClass" value="zh.maven.SQuartz.task.SimpleFirstTask" />
    <property name="jobDataMap">
        <map>
            <entry key="firstService" value-ref="simpleFirstService" />
        </map>
    </property>
</bean>
<bean id="simpleFirstService" class="zh.maven.SQuartz.service.SimpleFirstService"></bean>

The start delay time is specified, and the repetition interval time has been repeated to limit the number of times. The viewing table is as follows:

mysql> select * from qrtz_simple_triggers;
+-------------+--------------------+------------------+--------------+-----------------+-----------------+
| SCHED_NAME  | TRIGGER_NAME       | TRIGGER_GROUP    | REPEAT_COUNT | REPEAT_INTERVAL | TIMES_TRIGGERED |
+-------------+--------------------+------------------+--------------+-----------------+-----------------+
| myScheduler | firstSimpleTrigger | firstSimpleGroup |            5 |            2000 |               1 |
+-------------+--------------------+------------------+--------------+-----------------+-----------------+

TIMES_TRIGGERED is used to record how many times it has been executed. This value is defined in SimpleTriggerImpl. Each time it executes +1, the REPEAT_COUNT=5 defined here will be executed 6 times in reality. For details, you can view the SimpleTriggerImpl source code:

public Date getFireTimeAfter(Date afterTime) {
        if (complete) {
            return null;
        }
 
        if ((timesTriggered > repeatCount)
                && (repeatCount != REPEAT_INDEFINITELY)) {
            return null;
        }
        ......
}

The default value of timesTriggered is 0. When timesTriggered > repeatCount stops the trigger, so it will be executed 6 times, and the record will be deleted after the execution is completed;

4. qrtz_simprop_triggers
stores two types of triggers, CalendarIntervalTrigger and DailyTimeIntervalTrigger. Use CalendarIntervalTrigger to configure the following:

<bean id="firstCalendarTrigger" class="org.quartz.impl.triggers.CalendarIntervalTriggerImpl">
    <property name="jobDataMap">
        <map>
            <entry key="jobDetail" value-ref="firstCalendarTask"></entry>
        </map>
    </property>
    <property name="key" ref="calendarTriggerKey"></property>
    <property name="repeatInterval" value="1" />
    <property name="group" value="firstCalendarGroup"></property>
</bean>
<bean id="firstCalendarTask"
    class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
    <property name="jobClass" value="zh.maven.SQuartz.task.CalendarFirstTask" />
    <property name="jobDataMap">
        <map>
            <entry key="firstService" value-ref="calendarFirstService" />
        </map>
    </property>
</bean>
<bean id="calendarFirstService" class="zh.maven.SQuartz.service.CalendarFirstService"></bean>

CalendarIntervalTrigger does not have a corresponding FactoryBean, and directly sets the implementation class CalendarIntervalTriggerImpl; the specified repetition period is 1, and the default unit is days, that is, it is executed once a day. The viewing table is as follows:

mysql> select * from qrtz_simprop_triggers;
+-------------+--------------------+--------------------+------------+---------------+------------+------------+------------+-------------+-------------+------------+------------+-------------+-------------+
| SCHED_NAME  | TRIGGER_NAME       | TRIGGER_GROUP      | STR_PROP_1 | STR_PROP_2    | STR_PROP_3 | INT_PROP_1 | INT_PROP_2 | LONG_PROP_1 | LONG_PROP_2 | DEC_PROP_1 | DEC_PROP_2 | BOOL_PROP_1 | BOOL_PROP_2 |
+-------------+--------------------+--------------------+------------+---------------+------------+------------+------------+-------------+-------------+------------+------------+-------------+-------------+
| myScheduler | calendarTriggerKey | firstCalendarGroup | DAY        | Asia/Shanghai | NULL       |          1 |          1 |           0 |           0 |       NULL |       NULL | 0           | 0           |
+-------------+--------------------+--------------------+------------+---------------+------------+------------+------------+-------------+-------------+------------+------------+-------------+-------------+

Provides 3 parameters of type string, 2 parameters of type int, 2 parameters of type long, 2 parameters of type decimal and 2 parameters of type boolean; what is the meaning of each parameter, according to different trigger types Store their respective parameters;

5. qrtz_fired_triggers
stores the trigger related information that has been triggered. The trigger status changes over time until the trigger execution is completed and is deleted from the table; SimpleTrigger has been repeated 3 times as an example to query the table:

mysql> select * from qrtz_fired_triggers;
+-------------+----------------------------------------+--------------------+------------------+---------------------------+---------------+---------------+----------+-----------+-----------------+-----------+------------------+-------------------+
| SCHED_NAME  | ENTRY_ID                               | TRIGGER_NAME       | TRIGGER_GROUP    | INSTANCE_NAME             | FIRED_TIME    | SCHED_TIME    | PRIORITY | STATE     | JOB_NAME        | JOB_GROUP | IS_NONCONCURRENT | REQUESTS_RECOVERY |
+-------------+----------------------------------------+--------------------+------------------+---------------------------+---------------+---------------+----------+-----------+-----------------+-----------+------------------+-------------------+
| myScheduler | NJD9YZGJ2-PC15241041777351524104177723 | firstSimpleTrigger | firstSimpleGroup | NJD9YZGJ2-PC1524104177735 | 1524104178499 | 1524104178472 |        0 | EXECUTING | firstSimpleTask | DEFAULT   | 0                | 0                 |
| myScheduler | NJD9YZGJ2-PC15241041777351524104177724 | firstSimpleTrigger | firstSimpleGroup | NJD9YZGJ2-PC1524104177735 | 1524104180477 | 1524104180472 |        0 | EXECUTING | firstSimpleTask | DEFAULT   | 0                | 0                 |
| myScheduler | NJD9YZGJ2-PC15241041777351524104177725 | firstSimpleTrigger | firstSimpleGroup | NJD9YZGJ2-PC1524104177735 | 1524104180563 | 1524104182472 |        0 | ACQUIRED  | NULL            | NULL      | 0                | 0                 |
+-------------+----------------------------------------+--------------------+------------------+---------------------------+---------------+---------------+----------+-----------+-----------------+-----------+------------------+-------------------+

The same trigger and task will create an instance every time they are triggered; from the ACQUIRED state that was just created, to the EXECUTING state, and finally deleted from the database after execution;

6. qrtz_triggers
stores the defined triggers. Take the three triggers defined above as an example: firstSimpleTrigger, firstCalendarTrigger and firstCronTrigger. View the database after running:

mysql> select * from qrtz_triggers;
+-------------+--------------------+--------------------+-------------------+-----------+-------------+----------------+----------------+----------+---------------+--------------+---------------+----------+---------------+---------------+----------+
| SCHED_NAME  | TRIGGER_NAME       | TRIGGER_GROUP      | JOB_NAME          | JOB_GROUP | DESCRIPTION | NEXT_FIRE_TIME | PREV_FIRE_TIME | PRIORITY | TRIGGER_STATE | TRIGGER_TYPE | START_TIME    | END_TIME | CALENDAR_NAME | MISFIRE_INSTR | JOB_DATA |
+-------------+--------------------+--------------------+-------------------+-----------+-------------+----------------+----------------+----------+---------------+--------------+---------------+----------+---------------+---------------+----------+
| myScheduler | calendarTriggerKey | firstCalendarGroup | firstCalendarTask | DEFAULT   | NULL        |  1524203884719 |  1524117484719 |        5 | WAITING       | CAL_INT      | 1524117484719 |        0 | NULL          |             0 |          |
| myScheduler | firstCronTrigger   | firstCronGroup     | firstTask         | DEFAULT   | NULL        |  1524117492000 |  1524117486000 |        0 | ACQUIRED      | CRON         | 1524117483000 |        0 | firstCalendar |             0 |          |
| myScheduler | firstSimpleTrigger | firstSimpleGroup   | firstSimpleTask   | DEFAULT   | NULL        |             -1 |  1524117488436 |        0 | COMPLETE      | SIMPLE       | 1524117484436 |        0 | NULL          |             0 |          |
+-------------+--------------------+--------------------+-------------------+-----------+-------------+----------------+----------------+----------+---------------+--------------+---------------+----------+---------------+---------------+----------+

Unlike qrtz_fired_triggers, no matter how many times the trigger is triggered, there is only one record. TRIGGER_STATE is used to identify the current trigger state; firstCalendarTask is executed once a day, and it is always in the WAITING state after execution; firstCronTrigger is executed every 6 seconds and the state is ACQUIRED state ;The state of firstSimpleTrigger is COMPLETE after repeated execution 6 times, and it will be deleted;

7. qrtz_job_details
stores jobDetails information, and the relevant information is specified at the time of definition, such as the JobDetailFactoryBean defined above, to query the database:

mysql> select * from qrtz_job_details;
+-------------+-------------------+-----------+-------------+-----------------------------------------+------------+------------------+----------------+-------------------+----------+
| SCHED_NAME  | JOB_NAME          | JOB_GROUP | DESCRIPTION | JOB_CLASS_NAME                          | IS_DURABLE | IS_NONCONCURRENT | IS_UPDATE_DATA | REQUESTS_RECOVERY | JOB_DATA |
+-------------+-------------------+-----------+-------------+-----------------------------------------+------------+------------------+----------------+-------------------+----------+
| myScheduler | firstCalendarTask | DEFAULT   | NULL        | zh.maven.SQuartz.task.CalendarFirstTask | 0          | 0                | 0              | 0                 | |
| myScheduler | firstSimpleTask   | DEFAULT   | NULL        | zh.maven.SQuartz.task.SimpleFirstTask   | 0          | 0                | 0              | 0                 | |
| myScheduler | firstTask         | DEFAULT   | NULL        | zh.maven.SQuartz.task.FirstTask         | 0          | 0                | 0              | 0                 | |
+-------------+-------------------+-----------+-------------+-----------------------------------------+------------+------------------+----------------+-------------------+----------+

JOB_DATA stores the jobDataMap attribute specified when defining the task, so this attribute needs to implement the Serializable interface to facilitate persistence to the database;

8. qrtz_calendars
Quartz provides us with the function of calendar, you can define a time period by yourself, you can control the trigger to fire or not fire within this time period; now provides 6 types: AnnualCalendar, CronCalendar, DailyCalendar, HolidayCalendar, MonthlyCalendar, WeeklyCalendar ; The following uses CronCalendar as an example:

<bean id="firstCalendar" class="org.quartz.impl.calendar.CronCalendar">
    <constructor-arg value="0/5 * * ? * *"></constructor-arg>
</bean>
<bean id="firstCronTrigger"
    class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
    <property name="jobDetail" ref="firstTask" />
    <property name="cronExpression" value="0/6 * * ? * *" />
    <property name="group" value="firstCronGroup"></property>
    <property name="calendarName" value="firstCalendar"></property>
</bean>
<bean id="scheduler"
    class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="schedulerName" value="myScheduler"></property>
    <property name="dataSource" ref="dataSource" />
    <property name="configLocation" value="classpath:quartz.properties" />
    <property name="triggers">
        <list>
            <ref bean="firstCronTrigger" />
        </list>
    </property>
    <property name="calendars">
        <map>
            <entry key="firstCalendar" value-ref="firstCalendar"></entry>
        </map>
    </property>
</bean>

Define a CronCalendar that excludes every 5 seconds, then specify the calendarName in firstCronTrigger, and need to define calendars in SchedulerFactoryBean; because firstCronTrigger executes every 6 seconds, and CronCalendar excludes every 5 seconds, so firstCronTrigger will appear in the 5th It takes 12 seconds to wait for the first trigger, and the results are as follows:

20180419 15:09:06---start FirstService
20180419 15:09:08---end FirstService
20180419 15:09:12---start FirstService
20180419 15:09:14---end FirstService
20180419 15:09:18---start FirstService
20180419 15:09:20---end FirstService
20180419 15:09:24---start FirstService
20180419 15:09:26---end FirstService
20180419 15:09:36---start FirstService
20180419 15:09:38---end FirstService

Query the CronCalendar saved in the data:

mysql> select * from qrtz_calendars;
+-------------+---------------+----------+
| SCHED_NAME  | CALENDAR_NAME | CALENDAR |
+-------------+---------------+----------+
| myScheduler | firstCalendar | |
+-------------+---------------+----------+

CALENDAR stores the data serialized by CronCalendar;

9. qrtz_paused_trigger_grps
stores the paused triggers, and the test manually pauses the firstCronTrigger. The code is as follows:

public class App {
    public static void main(String[] args) {
        final AbstractApplicationContext context = new ClassPathXmlApplicationContext("quartz.xml");
        final StdScheduler scheduler = (StdScheduler) context.getBean("scheduler");
        try {
            Thread.sleep(4000);
            scheduler.pauseTriggers(GroupMatcher.triggerGroupEquals("firstCronGroup"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

After starting, pause firstCronTrigger after a delay of 4 seconds, pass the parameter group here, and then view the database:

mysql> select * from qrtz_paused_trigger_grps;
+-------------+----------------+
| SCHED_NAME  | TRIGGER_GROUP  |
+-------------+----------------+
| myScheduler | firstCronGroup |
+-------------+----------------+

Because it has been put into the library, the firstCronGroup is still in a suspended state after the restart, and the firstCronTrigger will not run;

10. qrtz_scheduler_state
stores the schedulers of all nodes, regularly checks whether the scheduler fails, starts multiple schedulers, and queries the database:

mysql> select * from qrtz_scheduler_state;
+-------------+---------------------------+-------------------+------------------+
| SCHED_NAME  | INSTANCE_NAME             | LAST_CHECKIN_TIME | CHECKIN_INTERVAL |
+-------------+---------------------------+-------------------+------------------+
| myScheduler | NJD9YZGJ2-PC1524209095408 |     1524209113973 |             1000 |
| myScheduler | NJD9YZGJ2-PC1524209097649 |     1524209113918 |             1000 |
+-------------+---------------------------+-------------------+------------------+

The latest check time is recorded, and CHECKIN_INTERVAL is set to 1000 in quartz.properties, which means checking every second;

11. qrtz_locks
The lock table provided by Quartz provides distributed locks for scheduling multiple nodes and realizes distributed scheduling. There are 2 locks by default:

mysql> select * from qrtz_locks;
+-------------+----------------+
| SCHED_NAME  | LOCK_NAME      |
+-------------+----------------+
| myScheduler | STATE_ACCESS   |
| myScheduler | TRIGGER_ACCESS |
+-------------+----------------+

STATE_ACCESS is mainly used when the scheduler regularly checks whether it is invalid to ensure that only one node handles the failed scheduler;
TRIGGER_ACCESS is mainly used when the TRIGGER is scheduled to ensure that only one node performs the scheduling;

Summary
This article makes a brief analysis of these 11 tables, introduces what each table is used to store, and gives simple examples; in fact, if you want to implement a trigger management system, it is actually for these Maintenance of tables.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324922660&siteId=291194637