十. 使用数据库存储 Scheduler 信息
·加载 Job 到数据库中
在前面有一节,"使用内存存储 Scheduler 信息",我们谈到关于在使用 RAMJobStore 时如何加载 Job 和 Trigger 信息到内存中。那么 Job 和 Trigger 又是如何加载到数据库中的呢?存在以下几个方法把 Job 信息存入到数据库:
· 在你的程序中加入 Job 信息
· 使用 JobInitializationPlugin
· 使用 Quartz Web 应用程序
我们在前面的 RAMJobStore 章节中讨论过前面两种途径。当它们用于 JDBC JobStore 时,并没有多大不同,只些许例外。首先,你需要知道,当使用这两个方法式,Job 信息是在数据库中的。甚至在你停止了程序后,这些信息仍然保留在数据库中。甚至是你不在你的程序中使用 JobInitializationPlugin 时,这些信息也还在数据库中。基于这一点,它是会从数据库中找寻 Job 信息。第八章涵盖了 JobInitializationPlugin 和常用的 Quartz 插件。
最后一种方法可能是最有意思的。我们还没有谈论到 Quartz Web 应用,但是我们在第十三章 "Quartz 和 Web 应用" 是这么做的。在现在呢,你应当知道 Quartz Web 应用是一个基于浏览器的 GUI 程序,它是设计用来管理 Quartz Scheduler。它是由 Quartz 用户设计的,它为加入 Job 和 Trigger、启动和暂停 Scheduler 和发布其他功能呈现了一个相当好的界面。
通过 SQL 工具加载 Job
最后还有一种能用于加载 Job 信息的方法,但仅在这儿提一下,并不鼓励你去尝试它。这种方法是使用本地 SQL 直接操作 Quartz 表来尝试加载和/或修改信息。使用本地查询工具来加入 Job 信息到数据库中只在少数时候这样做,但是很容易破坏数据进而导致所有 Job 不能正确运行。无论如何应尽力避免用这种方法。
十一. 使用 JobStoreCMT
许多我们在前面章节对 JobStoreTX 所说的和做的对于另一版本的 JDBC JobStore,JobStoreCMT 来也是适用的。再说,也没说所有,这不足为奇,因为它们都是 JobStore 类型,它们都是设计成用 JDBC 来与关系型数据库交互。也都是继承自共同的基类。
JobStoreCMT 被设计成参与到容器的事物边界内。这意味着容器创建一个 JTA 事物并使之对于 JobStore 可用。Quartz 与 JobStore 的交互保持在这个事物中。假如出现任何问题,Quartz 能给容器一个信号,它希望通过调用事物的 setRollbackOnly() 使事物回滚。
·配置 JobStoreCMT
同之前的 JobStoreTX 和 RAMJobStore 一样,要使用 JobStoreCMT 的第一步是告知 Scheduler 你打算用 JobStoreCMT。和以前类似,也是通过在 quartz.properties 文件中设置 JobStore 类属性来做到这一点的:
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreCMT
如果属性文件中存在 RAMJobStore 行,要确保移除了它。
·配置 DriverDelegate 类
你也是需要像为 JobStoreTX 所做的那样选择 DriverDelegate。Quartz 依靠一个 DriverDelegate 与给定的数据库通信。代理负责了与 JDBC Driver,也就是数据库的所有通信。
回到表 6.2 中的 DriverDelegate 列表,并基于你的数据库平台和环境选择一个。要加 MS SQLServer 代理到 quart.properties 文件,那就加入下一行:
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.MSSQLDelegate
你可以使几个属性来帮助调整 JobStoreCMT。表 6.5 列举了全部设置项。
表 6.5. 用于设置 JobStoreCMT 的配置属性
属性
默认值
org.quartz.jobStore.driverDelegateClass
描述:能够理解不同数据库系统中特定方言的驱动代理
org.quartz.jobStore.dataSource
描述:这是一个用于 quartz.properties 文件的数据源配置块的名字。
org.quartz.jobStore.nonManagedTXDataSource
描述: JobStoreCMT 需要一个(第二个) 数据源,它所包含的连接不作为容器管理事特的一部分。 这个属性值必须是一个定义在配置属性文件中的数据源的名字。这个数据源必须包含非容器管理事物(non-CMT) 连接,换名话说就是, 它产生的连接可让 Quartz 直接合法的调用它的 commit() 和 rollback() 方法。
org.quartz.jobStore.tablePrefix
QRTZ_
描述:这是指定给 Scheduler 的一套数据库表名的前缀。Schedulers 在指定了不同前缀时可在同一数据库中使用不同的表。
org.quartz.jobStore.useProperties
False
描述:"use properties" 标记指示着持久性 JobStore 所有在 JobDataMap 中的值都是字符串,因此能以 名-值 对的形式存储,而不用让更复杂的对象以序列化的形式存入 BLOB 列中。这样会更方便,因为让你避免了发生于序列化你的非字符串的类到 BLOB 时的有关类版本的问题。
org.quartz.jobStore.misfireThreshold
60000
描述:在 Trigger 被认为是错过触发之前,Scheduler 还容许 Trigger 通过它的下次触发时间的毫秒数(译者注:据原文翻译,真的不好理解,实际效果可参看:http://www.blogjava.net/Unmi/archive/2007/10/23/153413.html 我在评论中的实验)。默认值(假如你未在配置中存在这一属性条目) 是 60000(60 秒)。这个不仅限于 JDBC-JobStore;它也可作为 RAMJobStore 的参数
org.quartz.jobStore.isClustered
False
描述:设置此为 true 来打开集群特性。假如你有多个 Quartz 实例使用同一套数据库表时这个属性必须设置为 true。
org.quartz.jobStore.clusterCheckinInterval
15000
描述:设置一个频度(毫秒),用于实例报告给集群中的其他实例。这会影响到侦测失败实例的敏捷度。它只用于设置了 isClustered 为 true 的时候。
org.quartz.jobStore.maxMisfiresToHandleAtATime
20
描述: 这是 JobStore 能处理的错过触发的 Trigger 的最大数量。处理太多(超过两打) 很快会导致数据库表被锁定够长的时间,这样就妨碍了触发别的(还未错过触发) trigger 执行的性能。
org.quartz.jobStore.dontSetAutoCommitFalse
False
描述:设置这个参数为 true 则告诉 Quartz 不要调用从 DataSource 获取到的连接的 setAutoCommit(false) 方法. 这在少些情况下是有帮助的、例如你有一个驱动在已是 off 时又调用了这个方法会有所抱怨. 这个属性默认为 false,因为多数驱动需要调用 setAutoCommit(false) 方法。
org.quartz.jobStore.selectWithLockSQL
SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE
描述:这必须是一个从 LOCKS 表查询一行并对这行记录加锁的 SQL 语句。假如未设置,默认值就是 SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE,这能在大部分数据库上工作。{0} 会在运行期间被前面你配置的 TABLE_PREFIX 所替换。
org.quartz.jobStore.dontSetNonManagedTX
ConnectionAutoCommitFalse
False
描述:这个属性同 org.quartz.jobStore.dontSetAutoCommitFalse, 只是它还可以应用于不受管理事物的数据源(nonManagedTXDataSource)。
org.quartz.jobStore.txIsolationLevelSerializable
False
描述:值为 True 时告诉 Quartz (当使用 JobStoreTX 或 CMT 时) 调用 JDBC 连接的 setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE) 方法。这能助于防止某些数据库在高负荷和长事物时的锁超时。
org.quartz.jobStore.txIsolationLevelReadCommitted
False
描述:当设置为 true 时,这一属性告诉 Quartz 调用不受管理的 JDBC 连接的 setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED) 方法。这能助于防止某些数据库(如 DB2) 在高负荷和长事物时的锁超时。