欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

druid连接池异常

程序员文章站 2022-05-11 15:07:03
...

在从excel导入10W条数据到mysql中时,运行一段时间就会抛这个异常,连接池问题

org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is org.hibernate.TransactionException: JDBC begin failed:
Caused by: java.sql.SQLException: connection holder is null
	at com.alibaba.druid.pool.DruidPooledConnection.checkState(DruidPooledConnection.java:1085)
	at com.alibaba.druid.pool.DruidPooledConnection.getMetaData(DruidPooledConnection.java:825)
	at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:285)

找了下解决方案
1.

给jdbc url 增加 autoReconnect=true 一定能解决你的问题,可以定期观察一下 show processlist
改进方法如下:
<property name="url" value="jdbc:mysql://localhost/数据库实例名称?&useUnicode=true&characterEncoding=utf-8&autoReconnect=true"/>

2.

寻找支持重连的连接池。
           注意:c3p0连接池支持重连;重连参数是:
               idleConnectionTestPeriod   设置空闲连接测试周期
               preferredTestQuery : 设置一查询语句,用于重连测试
              testConnectionOnCheckin设置为true
              testConnectionOnCheckout设置为true

在sessionFactory里配置:

<property name="hibernateProperties">
   <props>

        <prop key="hibernate.autoReconnect">true</prop>

  </props>
</property>
这两种不同的配置都是使连接池自动重连

后面发现问题还是存在

通过研究源码我可以确定"Druid提供的getConnection()或者getConnection(long maxWaitMillis)方法不能保证在同一个线程中获取的始终是一个连接,直到显示的将连接关闭吗?"。必须在程序在缓存从Druid中取出的连接才能保证现一个事务在使用的是同一个连接。

而抛出“connection holder is null”异常的原因可能在于:

关闭长时间不使用的连接超时时间,单位秒
removeAbandonedTimeout

假设这个参数的值 为30分钟,当一个连接在获取后30分钟还没释放,也就是Connection的DruidPooledPreparedStatement对象执行完了executXXX()方法但还未执行close、commit、rollback方法,对应于Connection的running参数的值为false,这时Durid的DestroyConnectionThread线程会自动将该连接回收。当程序要commit()连接时会执行checkState()方法,这个方法会执行以下代码:

if (holder == null) {  
 if (disableError != null) {  
   throw new SQLException("connection holder is null", disableError);  
    } else {  
   throw new SQLException("connection holder is null");  
    }  
} 


这段代码就是我们看到的“connection holder is null”异常的来源,因此,我们需要做的就是根据Druid提供的监控信息(主要看“连接持有时间分布”的值)修改这个参数的值,它的值一定要比最长的连接持有时间还要大。

最后我把链接自动清除配置关闭解决了问题
removeAbandoned=false
如果把这个时间调整大一点应该也是可以的
removeAbandonedTimeout=1800
相关标签: mysql java excel