公众号

String boot @Scheduled和数据库连接池的 APPARENT DEADLOCK各种异常

- - 阅 19

一般来说,采用Spring Boot+MyBatis,无论是使用c3p0这样的老牌数据库连接池,还是使用Druid这样的阿里出品的数据库连接池,一般都不会有问题。我用Spring Boot做了一个基于JWT统一登录的微服务,采用的就是c3p0,几个月不登陆,也没出现数据库 APPARENT DEADLOCK!!! Complete Status:,No operations allowed after connection closed等等这样的异常,但是使用了@Scheduled后,数据库连接池频繁出现上述两种异常,天天死给我看,搞得我非常不爽,我想肯定是@Scheduled的问题,但是究竟出了什么问题?网上搜索了一阵资料后,大致明白了其中道理。

1)无论是APPARENT DEADLOCK!!!还是No operations allowed after connection closed都是数据库连接池超时或者使用了已经关闭的连接池造成的。那么为什么会出现这样的问题呢?

A)数据库连接池也是客户端/服务器端两端通信的问题,要么客户端连接服务器时,服务器无响应(例如mysql8小时的问题,mysql数据库把来自客户端的请求关闭了),要么

B) 是客户端自身本身的Connection 已经关闭了,但是新的Object Instance 还是使用了该Connection,则就出错了,这时可通过配置

<property name=”maxPoolSize” value=”300″ />
<property name=”minPoolSize” value=”10″ />
<property name=”maxIdleTime” value=”1800″ />
<property name=”maxStatements” value=”0″ />
<property name=”maxStatementsPerConnection” value=”100″/>
<property name=”initialPoolSize” value=”10″ />
<property name=”idleConnectionTestPeriod” value=”1800″ />
<property name=”testConnectionOnCheckin” value=”true” />
<property name=”automaticTestTable” value=”Test” />
<property name=”testConnectionOnCheckout” value=”false” />
<property name=”breakAfterAcquireFailure” value=”false” />

调整这些参数解决,Connection 即该关闭的及时关闭,不要长时间打开不关

C)Spring Boot @Scheduled的坑,@Scheduled长期打开的是同一个Class的同一个Object Instance,即Java的 JVM并没有把该Object销毁并进行内存回收,那么同一个Object Instance—–>Mybatis –>JDBC–>Database获取数据库连接池的路径,C3P0还是返回原来的那老一个,但是那老一个早已经被销毁,所以就会出现 APPARENT DEADLOCK!!!的问题。

解决的办法要么通过Http Client请求该定时器,例如采用Quartz或者Elstic JOB等外部中间件,Http调用每次都会生成一个新的线程,新的线程会生成新的Object,这时新的Object 从C3P0数据库连接池获取Connection时,就会返回新的Connection

要么定制一下Spring @Scheduled源代码(待续)

0

本文转载 " "

原文地址 " "

相关文章!