quartz异常:Couldn't rollback jdbc connection

最近工作发现,有个项目偶尔会报Couldn’t rollback jdbc connection. No operations allowed after connection closed,项目技术选型如下:

数据库mysql
连接池druid
quartz
从异常来看,是jdbc连接关闭后,代码中依然拿出来使用了,从而报错。进一步了解到,mysql连接默认的最长维持时间是8小时,即建立连接后,如果8小时内客户端没关闭连接,mysql就会把连接关闭,如果客户端拿到了这个连接,就会报错了。这种情况一般会发生在连接池的情况下,因为在连接池中,为了提高资源利用率,连接使用完之后一般不会关闭,而是返回连接池中,等待下次使用。

网上提供的解决方法如下:

延长mysql的连接维持时间,需要修改mysql配置;
从连接池中获取连接时,校验连接的有效性。
以上两种方法一个是从服务端出发,一个是从客户端出来。由于mysql权限问题,无法直接修改mysql的配置,因此只能从客户端入手了。

项目中使用的连接池是druid,理所当然是druid的问题,baidu了下一圈下来,druid相关的设置如下:

<!-- 获取连接时检查连接是否可用,官方说会影响性能,不建议开启-->
<property name="testOnBorrow" value="false" />
<!-- 归还连接时检查连接是否可用,官方说会影响性能,不建议开启-->
<property name="testOnReturn" value="false" />
<!-- 空闲时检查,再配合多久检查一次,官方建议使用的方式 -->
<property name="testWhileIdle" value="true" />
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 检查语句 -->
<property name="validationQuery" value="SELECT 'x'" />

对照项目中的配置发现,两者基本一致。看来问题并不在druid。

再分析异常信息,发现报错都是在quartz相关的类中,因此将焦点转向了quartz。

在quartz中,发现有一段配置是这样的:

<bean id="schedulerFactoryBean"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false">
  <property name="quartzProperties">
  	<props>
  	  <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
  	  <prop key="org.quartz.threadPool.threadCount">50</prop>
  	  <prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
  	  <prop key="org.quartz.jobStore.driverDelegateClass">org.quartz.impl.jdbcjobstore.StdJDBCDelegate</prop>
  	  <prop key="org.quartz.jobStore.dataSource">member</prop>
  	  <prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
	  	<!-- quartz数据库配置 -->
  	  <prop key="org.quartz.dataSource.member.driver">com.mysql.jdbc.Driver</prop>
  	  <prop key="org.quartz.dataSource.member.URL">${member.jdbc.url}</prop>
  	  <prop key="org.quartz.dataSource.member.user">${member.jdbc.username}</prop>
  	  <prop key="org.quartz.dataSource.member.password">${member.jdbc.password}</prop>
  	  <prop key="org.quartz.dataSource.member.maxConnections">10</prop>
  	</props>
  </property>
</bean>

这里可以发现,quartz并没有使用druid连接池,而是重新开启数据库连接。在quartz 2.2.1 jdbc 连接池参数配置中,知道了quartz默认的连接是c3p0,并且了解了相关配置项。继续搜索,发现有人也踩过这个坑:quartz和数据库断连接的解决办法,结合这两篇文章,我给出的解决方案如下:

<bean id="schedulerFactoryBean"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false">
  <property name="quartzProperties">
  	<props>
  	  <prop key="org.quartz.threadPool.class">org.quartz.simpl.SimpleThreadPool</prop>
  	  <prop key="org.quartz.threadPool.threadCount">50</prop>
  	  <prop key="org.quartz.jobStore.class">org.quartz.impl.jdbcjobstore.JobStoreTX</prop>
  	  <prop key="org.quartz.jobStore.driverDelegateClass">org.quartz.impl.jdbcjobstore.StdJDBCDelegate</prop>
  	  <prop key="org.quartz.jobStore.dataSource">member</prop>
  	  <prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
  	  <prop key="org.quartz.dataSource.member.driver">com.mysql.jdbc.Driver</prop>
  	  <prop key="org.quartz.dataSource.member.URL">${member.jdbc.url}</prop>
  	  <prop key="org.quartz.dataSource.member.user">${member.jdbc.username}</prop>
  	  <prop key="org.quartz.dataSource.member.password">${member.jdbc.password}</prop>
  	  <prop key="org.quartz.dataSource.member.maxConnections">10</prop>
  	  <!-- 添加的配置 -->
  	  <prop key="org.quartz.dataSource.member.validateOnCheckout">true</prop>
  	  <prop key="org.quartz.dataSource.member.validationQuery">SELECT 'x'</prop>
  	</props>
  </property>
</bean>

只是在quartz配置文件中添加了两行:

<!-- 从连接池中获取连接时,验证连接是否有效 -->
<prop key="org.quartz.dataSource.member.validateOnCheckout">true</prop>
<!-- 验证语句 -->
<prop key="org.quartz.dataSource.member.validationQuery">SELECT 'x'</prop>

源著:https://my.oschina.net/funcy/blog/2045908

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值