事务和调度程序
缺省情况下,调度程序在单个全局事务中运行任务。可以使用 QOS_ONLYONCE 或 QOS_ATLEASTONCE 服务质量来指定任务是作为单个工作单元运行一次还是作为独立的事务运行。
运行任务时的事务行为
由于调度程序在单个全局事务中运行任务,所以在缺省情况下,事务会保持打开状态,直到任务完成或失败为止。涉及该事务的资源受各种超时约束,如果任务的运行时间超过允许值数分钟甚至数小时,那么可能会将任务的线程标识为挂起。
QOS_ONLYONCE
- 创建了任务的应用程序的上下文将应用到线程。
- 启动了一个全局事务上下文。
- 使用 UserCalendar Bean 或 DefaultUserCalendar 计算下一次触发时间和启动时间。要点: 如果将 TaskInfo.setTaskExcecutionOptions 方法与 TaskInfo.EXECUTION_DELAYEDUPDATE 选项配合使用,那么此步骤将在更新记录之后出现。
- 在数据库中使用下一个任务的状态更新任务数据库任务记录,如果任务已完成并且任务的自动清除设置为 true,那么删除任务记录。
- 在数据库中使用下一个任务的状态更新任务数据库记录,如果任务已完成并且任务的自动清除设置为 true,那么删除任务记录。如果使用了 EXECUTION_DELAYEDUPDATE 选项,那么数据库不会影响任务的下一个状态,但当前状态会设置为 TaskStatus.RUNNING 状态。
- 如果设置了 NotificationSink Bean,将触发 FIRING 通知。
- BeanTaskInfo 或 MessageTaskInfo 对象启动。
- 如果任务失败并且设置了 NotificationSink Bean,将在一个独立事务中触发 FIRE_FAILED 通知。
- 如果设置了任务的 NotificationSink Bean,那么根据需要触发各个通知。
- 如果对任务使用 EXECUTION_DELAYEDUPDATE 选项,那么会用任务的下一个状态再次更新数据库。
- 落实全局事务。
- 参加任务事务的每个资源必须具有两阶段 XA 能力。
其中包括为调度程序配置的 Java™ 数据库连接 (JDBC) 数据源、MessageTaskInfo 对象使用的任何 Java 消息服务 (JMS) 服务以及任何具有事务设置“Required”的 UserCalendar、TaskHandler 或 NotificationSink Bean 中使用的任何资源。
- 如果为创建了事务的应用程序启用了“最后参与者支持”,那么资源可以是一阶段资源。使用组装工具启用“最后参与者支持”。也可以通过管理控制台启用“最后参与者支持”。有关详细信息,请参阅“最后参与者支持扩展设置”主题。
会将所有意外异常记录到活动日志中,且会回滚参与任务的全局事务的所有事件。其中包括对任务的数据库记录的更改,当调度程序守护程序在下一个轮询周期中轮询数据库时,这些更改会强制再次执行任务。UserCalendar、TaskHandler 和 NotificationSink Bean 可以通过将 Bean 的事务设置配置为“Requires new”,选择不参与全局事务。
QOS_ATLEASTONCE
- 创建了任务的应用程序的上下文将应用到线程。
- 用 RUNNING 任务状态更新了任务的数据库记录。
- 调用了 UserCalendar 和 NotificationSink Bean。
- 启动了 BeanTaskInfo 或 MessageTaskInfo。
- 发送了结果通知。
- 如果未更改任务,那么由于写入了 RUNNING 状态,所以用任务的下一个状态更新数据库。
如果在将 RUNNING 状态写入数据库之后但在写入结果之前发生故障,那么该任务可能会运行多次。
在使用 QOS_ATLEASTONCE 时,由于在任务运行时没有全局事务可用,因此所有 NotificationSink、UserCalendar 和 TaskHandler Bean 都不能托管事务 (TX_MANDATORY)。EJB 组件使用“Required”或“Requires new”容器管理的事务或 Bean 管理的事务。
使用 Scheduler API 方法或 WASScheduler MBean 操作时的事务行为
所有 Scheduler 接口方法都参与一个全局事务上下文。如果在执行 create()、suspend()、resume()、cancel() 和 purge() 方法时全局事务上下文在线程上已经存在,那么会使用现有全局事务。否则,将启动一个新的全局事务。
如果方法参与调用者的全局事务并且出现意外错误,事务将被标记为回滚。如果异常是一个已声明的异常,那么将把它重新提交给调用者,并且由调用者决定落实还是回滚事务。
如果方法启动了自己的全局事务并出现任何异常,将回滚事务并将异常重新提交给调用者。