DataSource.getConnection 方法在数据库重启或理想超时后返回一个已经关闭的连接

Posted

技术标签:

【中文标题】DataSource.getConnection 方法在数据库重启或理想超时后返回一个已经关闭的连接【英文标题】:DataSource.getConnection method returns an already closed connection after database restart or ideal timeout 【发布时间】:2017-12-22 06:45:43 【问题描述】:

这是我从DataSource获取数据库Connection的代码

DataSource dataSource = DataSourceBuilder.create().url(url).username(userName).password(password).driverClassName(dataSourceReader.getSqlServerDriverClassName()).build();
Connection connection  = dataSource.getConnection();
System.out.println(connection.isClosed()); //Print false

如果发生连续的数据库操作,一切正常。 如果我将我的应用程序理想化一段时间(连接超时)或者我重新启动我的数据库服务器并尝试执行上面相同的代码,我会关闭连接并且connection.isClosed() 的输出为真, 此外,如果我对 connection 执行任何操作,它会抛出异常

com.microsoft.sqlserver.jdbc.SQLServerException: The connection is closed.
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:190) ~[sqljdbc4-4.0.jar!/:na]
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.checkClosed(SQLServerConnection.java:388) ~[sqljdbc4-4.0.jar!/:na]
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.prepareCall(SQLServerConnection.java:2176) ~[sqljdbc4-4.0.jar!/:na]
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.prepareCall(SQLServerConnection.java:1861) ~[sqljdbc4-4.0.jar!/:na]
    at sun.reflect.GeneratedMethodAccessor148.invoke(Unknown Source) ~[na:na]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_45]
    at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_45]
    at org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:126) ~[tomcat-jdbc-8.5.6.jar!/:na]
    at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:108) ~[tomcat-jdbc-8.5.6.jar!/:na]
    at org.apache.tomcat.jdbc.pool.DisposableConnectionFacade.invoke(DisposableConnectionFacade.java:81) ~[tomcat-jdbc-8.5.6.jar!/:na]
    at com.sun.proxy.$Proxy100.prepareCall(Unknown Source) ~[na:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_45]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_45]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_45]
    at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_45]

令人惊讶的是,重新启动我的 java 应用程序后,相同的代码可以正常工作。

对处理这种情况有什么建议吗?

我可以重新打开关闭的连接吗?

更多细节:

Java 版本:1.8.0_25 应用服务器:带有 Spring Boot 的 Tomcat 8 数据库:Microsoft SQL Server 标准版(64 位)版本 10.50.1617.0 数据库驱动:com.microsoft.sqlserver:sqljdbc4:4.0'

【问题讨论】:

【参考方案1】:

为了稳健,您的应用程序应设计为处理连接异常,因为它们可能(并且确实)在企业环境中出于多种原因发生。处理此问题的一种方法是简单地从连接对象中捕获 sql 异常并尝试再次获取连接,直到您成功或达到您设置的重试限制。根据环境以及 jdbc 驱动程序或应用服务器是否正在执行连接池,您可能需要重试,直到池自行清除失败的连接。您可能希望将重试限制为任何连接池的大小,以免无限循环。

【讨论】:

我使用了BasicDataSource的dbcp,它在连接超时和数据库重启后工作。它解决了我的问题

以上是关于DataSource.getConnection 方法在数据库重启或理想超时后返回一个已经关闭的连接的主要内容,如果未能解决你的问题,请参考以下文章

Aspect 失败,ClassCastException 试图切入 Tomcat DataSource getConnection

Jdbc非学术性地理解DataSource和Jdbc

在 Derby 客户端驱动程序中提供连接超时

聊聊hikari连接池的isAllowPoolSuspension

JDBC资源的正确使用方式

从 JDBC MSSQL 获取返回值