jtds - HikariCP 卡在 getConnection 上

标签 jtds hikaricp

我有一个应用程序,它使用 HikariCP 对使用 JTDS 的 SQL Server DB 进行连接池。如果我让应用程序运行过夜,早上第一个查询将挂起,并显示下面的堆栈跟踪。如果我再次请求,那么新的查询将正常工作。我是否缺少一个超时来阻止第一个查询挂起?它似乎挂起大约 10->20 分钟,然后开始工作。因此,10->20 分钟后,sockRead 和挂起的线程就会消失。我认为挂起的查询随后完成,但我可能是错的。我的 Hikari 配置也如下。

java.lang.Thread.State: RUNNABLE
      at java.net.SocketInputStream.socketRead0(SocketInputStream.java:-1)
      at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
      at java.net.SocketInputStream.read(SocketInputStream.java:170)
      at java.net.SocketInputStream.read(SocketInputStream.java:141)
      at java.io.DataInputStream.readFully(DataInputStream.java:195)
      at java.io.DataInputStream.readFully(DataInputStream.java:169)
      at net.sourceforge.jtds.jdbc.SharedSocket.readPacket(SharedSocket.java:850)
      at net.sourceforge.jtds.jdbc.SharedSocket.getNetPacket(SharedSocket.java:731)
      - locked <0xeeb> (a java.util.concurrent.ConcurrentHashMap)
      at net.sourceforge.jtds.jdbc.ResponseStream.getPacket(ResponseStream.java:477)
      at net.sourceforge.jtds.jdbc.ResponseStream.read(ResponseStream.java:114)
      at net.sourceforge.jtds.jdbc.ResponseStream.peek(ResponseStream.java:99)
      at net.sourceforge.jtds.jdbc.TdsCore.wait(TdsCore.java:4127)
      at net.sourceforge.jtds.jdbc.TdsCore.executeSQL(TdsCore.java:1086)
      - locked <0xeec> (a net.sourceforge.jtds.jdbc.TdsCore)
      at net.sourceforge.jtds.jdbc.JtdsStatement.executeSQL(JtdsStatement.java:563)
      at net.sourceforge.jtds.jdbc.JtdsStatement.executeImpl(JtdsStatement.java:809)
      at net.sourceforge.jtds.jdbc.JtdsStatement.execute(JtdsStatement.java:1282)
      at com.zaxxer.hikari.pool.PoolElf.isConnectionAlive(PoolElf.java:224)
      at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:188)
      at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:163)
      at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:85)
      at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:204)
      at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373)
      at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130)

光配置:

hconf.setJdbcUrl(url) // url looks like: jdbc:jtds:sqlserver://host/DB
hconf.setConnectionTestQuery("select 1")
hconf.setDriverClassName("net.sourceforge.jtds.jdbcx.JtdsDataSource")
// set username and password

hconf.setConnectionTimeout(5 * 1000)
hconf.setValidationTimeout(1000)
hconf.setIdleTimeout(10 * 60 * 1000)
hconf.setMaxLifetime(30 * 60 * 1000)
hconf.setLeakDetectionThreshold(60 * 1000)
hconf.setInitializationFailFast(false)
val numThreads = 10
hconf.setMaximumPoolSize(numThreads * 5)
hconf.setMinimumIdle(numThreads)
hconf.setPoolName(name)
hconf.setRegisterMbeans(false)

光CP:2.4.1

JTDS:1.3.1

更新:

我现在知道问题出在哪里了。在 HikariCP isConnectionAlive 中,它会在调用 setConnectionTestQuery 中设置的查询之前尝试将网络超时设置为上面 setValidationTimeout 中指定的值。但是,JTDS 不支持 java.sql.Connection.setNetworkTimeout,因此读取超时是操作系统默认值。大约需要 10 分钟。

理论上,您应该能够设置驱动程序属性套接字超时作为解决方法(尽管它对我不起作用)。但这并不是一个很好的解决方法,因为您确实希望测试查询与实际查询的查询超时不同。

所以这不是 HikariCP 问题,而是 JTDS 问题。

最佳答案

我建议通过 log4j 或您正在使用的任何日志框架为 HikariCP 包启用调试级别日志记录。 HikariCP 应记录连接停用和创建,您可以使用它来验证连接是否在其配置的 maxLifetime 处正确循环。

但是,查看您发布的堆栈跟踪,在 HikariCP isConnectionAlive() 检查期间,该线程似乎卡在 JTDS 驱动程序中。 HikariCP 在这里无能为力。不过这很奇怪。

您说“早上第一个查询将挂起”。电脑要休眠了吗? SQL Server 会休眠吗?这样做会阻止 HikariCP 在夜间正常循环连接。同样,调试日志记录在这里会有所帮助——即使应用程序处于空闲状态,夜间也应该有相当定期的停用和创建事件。

关于jtds - HikariCP 卡在 getConnection 上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34739778/

相关文章:

jdbc - 通过 sqljdbc.jar 使用 Windows 身份验证

java - 如何使用 jTDS 将表值参数传递给存储过程?

java - getdate() 通过结果集查询抛出无当前行异常

java - Presto JDBC 连接池创建错误 "Disabling auto-commit mode not supported"

java - 为什么 HikariCP 在关闭前一个数据库后不建立新的数据库连接?

java - 将 android 应用程序连接到 Microsoft SQL Server 2008

groovy - 将 groovy 连接到 sql server

postgresql - Spring Boot 2.1.4 + JDBI + HikariCP + PostgreSQL 发生错误后连接未释放到池

oracle - 对于现代应用程序,我应该使用 Oracle 的 UCP 还是 HikariCP?

mysql - "Packet for query is too large"在带有 mysql 的 java web 应用程序中