当前位置: 首页 > 知识库问答 >
问题:

使用unwrapped Oracle . JDBC . driver . t4c Connection的HikariCP连接泄漏

公西翼
2023-03-14

我在使用具有未包装连接的HikariCP时遇到资源泄漏问题。然后代码的一点解释。

我必须使用一个未包装的连接来访问Oracle methods for Oracle . SQL . bfile。

数据源示例:

private static DataSource unwrapDatasource;
public static synchronized DataSource getUnwrappedDataSource() {
    if (unwrapDatasource == null) {
        HikariConfig config = new HikariConfig();
        config.setMaximumPoolSize(50);
        config.setLeakDetectionThreshold(120000);
        config.setJdbcUrl(DATABASEURL);
        config.addDataSourceProperty("user", USERNAME);
        config.addDataSourceProperty("password", DBPASSWORD);
        config.addDataSourceProperty("driverType", "thin");
        config.setDriverClassName("oracle.jdbc.pool.OracleDataSource");
        config.setMaxLifetime(300000);
        config.setPoolName("UNWRAP");
        unwrapDatasource = new HikariDataSource(config);
    }

    return unwrapDatasource;
}

  public static Connection getUnwrappedConnection() {
    Connection con = null;
    try {
        con = this.getUnwrappedDataSource().getConnection().unwrap(oracle.jdbc.driver.OracleConnection.class);
    } catch (SQLException ex) {
        //logger junk ommitted for brevity
    }
    return con;
}

使用HikariCP-java7-2.4.12作为应用程序非常旧并且在tomcat-6上运行。这是被报告为泄漏的连接示例

    com.zaxxer.hikari.pool.ProxyLeakTask.run(poolProxyLeak.java:91) : <Connection leak detection triggered for {}, stack trace follows>
java.lang.Exception: Apparent connection leak detected
    at myapp.package.obfuscated.getUnwrapConnection(DataSourceConstants.java:253)
    at myapp.package.obfuscated.BB.execute(DatabaseCallingClass2.java:106)
    at myapp.package.obfuscated.BB.execute(DatabaseCallingClass2.java:85)
    at myapp.package.obfuscated.AA.execute(DataBaseCallingClass.java:52)
    at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:425)
    at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:228)
    at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1913)
    at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:462)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:643)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:723)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.displaytag.filter.ResponseOverrideFilter.doFilter(ResponseOverrideFilter.java:123)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:563)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:610)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:503)
    at java.lang.Thread.run(Thread.java:745)

以下是连接及其使用方式:

     Connection con = null;
     PreparedStatement pstmt = null;
     OracleResultSet rs = null;
     InputStream inputStream = null;
     StringBuilder stringBuilder = new StringBuilder(128);
     try {
            con = DataSourceConstants.getUnwrappedConnection();

            pstmt = con.prepareStatement("SELECT BFILENAME('ORACLE_DIR', 'fileDownload.12345') AS BFILE from dual" );  //hardcoded for example
            rs = (OracleResultSet) pstmt.executeQuery();

            rs.next();  //Assumption if rs.next() blows up, catch would grab it and resources would all attempt to close in finally block

            bfile = rs.getBFILE(1);
            bfile.open();
            inputStream = bfile.getBinaryStream();
            char c;
            long size = bfile.length();

            int i = 0;
            do {
                c= (char) inputStream.read();
                stringBuilder.append(c);
            } while (++i < size);

            } catch (Exception ex) {
              //logger ommitted but not throwing here
            } finally {
             //cleanup resources
             try { inputStream.close(); } catch (Exception ex) {}
             try { bfile.close(); } catch (Exception ex) {}
             try { rs.close(); } catch (Exception ex) {}
             try { pstmt.close(); } catch (Exception ex) {}
             try {con.close();  } catch (Exception ex){}
            }
       //use stringBuilder later in built output.

所以上面检索了一个未包装的T4CConnection,这样我就可以使用OracleResultSet和BFILE / getBFILE()。这是可行的,并且我得到了我想要的结果,但是使用这个结构来检索BFILE的两个单独的类都在泄漏,并且另一个不使用BFILE但是使用Unwrapped连接来使用OracleCallableStatement的方法也在泄漏。我已经实例化了3个数据源,按照类型/函数分割所有的连接器,唯一泄漏的池是使用Datasource.getConnection()的那个。为其连接器展开(Oracle . JDBC . driver . Oracle connection . class)。

我是否对未包装的连接执行了错误操作?为什么这是唯一一个泄漏的?这是一个已知的驱动程序错误吗?(我还没有想出任何关于它的文章)BFILE似乎不是很受欢迎...

共有1个答案

幸鸿轩
2023-03-14

您在getUnwrappeConnection()中所做的不是您应该做的:如果您正在解包装,那么您需要确保您还保留连接池连接,因为关闭该连接将其返回到池。因此,首先从池中获取连接,并且仅在您真正需要它的时候解包装,然后,当您完成后,关闭从数据源获得的原始连接。

不要关闭未打包的连接,因为这将关闭实际的物理连接,并且会破坏使用连接池的目的。

简而言之:

try (Connection connection = dataSource.getConnection()) {
    OracleConnection unwrapped = connection.unwrap(oracle.jdbc.driver.OracleConnection.class)

    ...

    // Do not close (or use try-with-resources) on unwrapped
}
 类似资料:
  • 我正在开发一个在Java服务器上运行的游戏。对于数据库池,我使用的是HikariCP,这是一个优秀的库,但它现在抛出了以下错误: 现在我知道连接泄漏意味着打开的连接在某个地方漂浮,但我不知道如何或在哪里漂浮。 下面是我的数据库类中的一个方法,根据堆栈跟踪,错误应该发生在这里。 这只是启动语句的一个基本方法。调用它时,我使用它,然后调用、和 但它告诉我连接是打开的。 我怎么解决这个?谢了!

  • 是否可以在2.3.9版本中启用泄漏检测?正如我之前在这个问题中所说,HiberNate使用的是HikariCP的2.3.3版本。截至2016年2月,他们已经升级了HikariCP的版本,但不幸的是升级到了2.3.9版本 我需要启用泄漏检测才能修复它们。我已将以下行添加到Hibernate配置文件中: 前两行运行正常,可以在调试日志中看到,但是当我添加第三行时,我无法运行应用程序。我也尝试过用代码添

  • 我的连接器类: 连接器。JAVA 这是我的DAO类(简化):UserDAO. java 在这里,我发现了关于Hikari的一些事实的问题: 您必须在HikariCP为您提供的连接实例上调用关闭() 可能是我的不起作用,因为它只是Hikari在方法中提供给我的连接的副本。

  • 我有一个Spring Boot(v2.0.8)应用程序,它使用HikariCP(v2.7.9)池(连接到MariaDB)配置: 问题在于,我们的生产组件每隔几周就会反复抛出 。问题在于它永远不会从中恢复,并且会不断引发异常。因此,需要重新启动计算装置。 从HikariPool源代码来看,这似乎正在发生,因为每次它调用poolEntry都是空的,因此会抛出超时异常。要使其为空,连接池必须没有空闲条目

  • 我正在运行一个Spring boot Java应用程序,使用默认的HikariCP作为数据源: Hikari版本-3.4.5 在AWS EKS中运行的Spring Boot version-2.4.5 JDBI版本-3.9.1 DB-AWS RDS Postgres 我的Spring应用程序变得没有响应,因为它失去了Hikari池中的所有连接。这并不是确定地发生,但是一旦它开始发生,唯一可能的恢复

  • 我们的项目中有Spring-boot/hibernate/PostgreSQL应用程序,并使用Hikari作为连接池。我们不断遇到以下问题:几个小时后,活动连接数增长到极限,我们得到如下错误(完整堆栈跟踪位于问题的末尾): 以下是版本信息: JPA/Hibernate配置: HikariCP配置: 完整堆栈跟踪: