石英在负载下会引发死锁

发布于 2024-08-26 00:48:24 字数 3261 浏览 5 评论 0原文

我们将 Quartz 与 Spring 结合使用,当 Quartz 配置了超过 1 个线程时,我们的配置会引发死锁。我开始相信这是因为我们没有使用 Spring 正确配置石英,但我找不到足够的文档来说明如何配置两者以使其更好地发挥作用。

我们在 Windows 和 Linux 环境上运行 - 指向 MSSQL 和 Oracle DB。对于两种操作系统,使用任一数据库,我们都可以抛出以下死锁错误......

我们一直抛出这些死锁错误。我们在重负载下运行,在几分钟内插入数百个石英触发器。

2010-03-17 18:52:31,737 [] [] ERROR [DFScheduler_Worker-42] core.ErrorLogger core.ErrorLogger (QuartzScheduler.java:2185) - An error occured while marking executed job complete. job= 'BPM.6e41a6567f0000020100362a51dc7a50'

org.quartz.JobPersistenceException: Couldn't remove trigger: Transaction (Process ID 87) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction. [See nested exception: com.microsoft.sqlserver.jdbc.SQLServerException: Transaction (Process ID 87) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.]
at org.quartz.impl.jdbcjobstore.JobStoreSupport.removeTrigger(JobStoreSupport.java:1469)at org.quartz.impl.jdbcjobstore.JobStoreSupport.triggeredJobComplete(JobStoreSupport.java:2978)at org.quartz.impl.jdbcjobstore.JobStoreSupport$39.execute(JobStoreSupport.java:2962) at org.quartz.impl.jdbcjobstore.JobStoreSupport$41.execute(JobStoreSupport.java:3713)at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3747)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3709)at org.quartz.impl.jdbcjobstore.JobStoreSupport.triggeredJobComplete(JobStoreSupport.java:2958)at org.quartz.core.QuartzScheduler.notifyJobStoreJobComplete(QuartzScheduler.java:1727)at org.quartz.core.JobRunShell.run(JobRunShell.java:273)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:534)

Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Transaction (Process ID 87) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(Unknown Source at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(Unknown Source) at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(Unknown Source) at 
...
org.quartz.impl.jdbcjobstore.StdJDBCDelegate.deleteSimpleTrigger(StdJDBCDelegate.java:1820) at org.quartz.impl.jdbcjobstore.JobStoreSupport.deleteTriggerAndChildren(JobStoreSupport.java:1345 at org.quartz.impl.jdbcjobstore.JobStoreSupport.removeTrigger(JobStoreSupport.java:1453 ... 9 more

这就是我的quartz.properties 文件的样子:

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 50
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties = false
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = false
org.quartz.jobStore.selectWithLockSQL = SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?

We are using Quartz with Spring and our configuration is throwing deadlocks when quartz has more than 1 thread configured. I'm starting to believe that it's because we don't have our quartz configured correctly with Spring, but I can't find enough documentation on how to configure the two to play nicely.

We are running on both Windows and Linux environments - pointing at MSSQL and Oracle DBs. With both OS, using either DB, we can throw the following deadlock errors...

We're consistently throwing these deadlock errors. We run under heavy load, inserting hundreds of quartz triggers in a matter of minutes.

2010-03-17 18:52:31,737 [] [] ERROR [DFScheduler_Worker-42] core.ErrorLogger core.ErrorLogger (QuartzScheduler.java:2185) - An error occured while marking executed job complete. job= 'BPM.6e41a6567f0000020100362a51dc7a50'

org.quartz.JobPersistenceException: Couldn't remove trigger: Transaction (Process ID 87) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction. [See nested exception: com.microsoft.sqlserver.jdbc.SQLServerException: Transaction (Process ID 87) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.]
at org.quartz.impl.jdbcjobstore.JobStoreSupport.removeTrigger(JobStoreSupport.java:1469)at org.quartz.impl.jdbcjobstore.JobStoreSupport.triggeredJobComplete(JobStoreSupport.java:2978)at org.quartz.impl.jdbcjobstore.JobStoreSupport$39.execute(JobStoreSupport.java:2962) at org.quartz.impl.jdbcjobstore.JobStoreSupport$41.execute(JobStoreSupport.java:3713)at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3747)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.executeInNonManagedTXLock(JobStoreSupport.java:3709)at org.quartz.impl.jdbcjobstore.JobStoreSupport.triggeredJobComplete(JobStoreSupport.java:2958)at org.quartz.core.QuartzScheduler.notifyJobStoreJobComplete(QuartzScheduler.java:1727)at org.quartz.core.JobRunShell.run(JobRunShell.java:273)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:534)

Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Transaction (Process ID 87) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(Unknown Source at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(Unknown Source) at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(Unknown Source) at 
...
org.quartz.impl.jdbcjobstore.StdJDBCDelegate.deleteSimpleTrigger(StdJDBCDelegate.java:1820) at org.quartz.impl.jdbcjobstore.JobStoreSupport.deleteTriggerAndChildren(JobStoreSupport.java:1345 at org.quartz.impl.jdbcjobstore.JobStoreSupport.removeTrigger(JobStoreSupport.java:1453 ... 9 more

This is what my quartz.properties file looks like:

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 50
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties = false
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = false
org.quartz.jobStore.selectWithLockSQL = SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

时光病人 2024-09-02 00:48:24

你使用 SchedulerFactoryBean 吗?该文档是: http://static.springsource.org/ spring/docs/2.5.x/reference/scheduling.html 它将完全消除对实际quartz.properties的需要,您可以使用在应用程序的其余部分中使用的数据源。这具有明显的优点(例如连接池中的可重用连接),并且至少对我来说提供了更轻松的调试时间。

这是我的旧项目中的片段:

<bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="quartzProperties"> <!--  quartz attributes, configurable -->
        <value>
            org.quartz.scheduler.rmi.export = false
            org.quartz.scheduler.rmi.proxy = false
            org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
            org.quartz.threadPool.threadCount = ${threadCount}
            org.quartz.threadPool.threadPriority = 5
            org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
            org.quartz.jobStore.useProperties = false
            org.quartz.jobStore.driverDelegateClass = ${driverDelegate}
            org.quartz.jobStore.tablePrefix = QRTZ_
            org.quartz.jobStore.isClustered = false
        </value>
    </property>
    <property name="autoStartup" value="false" /> 
    <property name="waitForJobsToCompleteOnShutdown" value="false" />
    <property name="dataSource" ref="dataSource" />
</bean>

以及通常的数据源:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    ....
    <property name="validationQuery" value="SELECT 1" />
    <property name="testWhileIdle" value="true" />
    <property name="testOnBorrow" value="true" />
    <property name="testOnReturn" value="true" />
</bean>

显然,quartzProperties 与文件中的类似,但是一旦我从 quarts 切换过来,我发现应用程序的一般行为更好。 Spring 类的属性。这也有助于我只有一个数据源实际访问数据库。

Do you use a SchedulerFactoryBean? The documentation is: http://static.springsource.org/spring/docs/2.5.x/reference/scheduling.html It would completely remove the need for the actual quartz.properties and you can use the datasource you use in the rest of the application. This has obvious advantages (like reusable connections in a connection pool) and at least for me offered a somewhat easier time debugging.

Here's a snippet of how mine looked like in an older project:

<bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="quartzProperties"> <!--  quartz attributes, configurable -->
        <value>
            org.quartz.scheduler.rmi.export = false
            org.quartz.scheduler.rmi.proxy = false
            org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
            org.quartz.threadPool.threadCount = ${threadCount}
            org.quartz.threadPool.threadPriority = 5
            org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true
            org.quartz.jobStore.useProperties = false
            org.quartz.jobStore.driverDelegateClass = ${driverDelegate}
            org.quartz.jobStore.tablePrefix = QRTZ_
            org.quartz.jobStore.isClustered = false
        </value>
    </property>
    <property name="autoStartup" value="false" /> 
    <property name="waitForJobsToCompleteOnShutdown" value="false" />
    <property name="dataSource" ref="dataSource" />
</bean>

and the datasource the usual:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    ....
    <property name="validationQuery" value="SELECT 1" />
    <property name="testWhileIdle" value="true" />
    <property name="testOnBorrow" value="true" />
    <property name="testOnReturn" value="true" />
</bean>

Obviously the quartzProperties are similar to the ones in the file, but I've found the general behavior of the application better once I switched from the quarts.properties to the Spring classes. It also helped that I had only one datasource actually accessing the database.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文