【发布时间】:2016-01-12 09:26:17
【问题描述】:
我有一个应用程序,它使用 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)
Hikari 配置:
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)
HikariCP:2.4.1
JTDS:1.3.1
更新:
我现在知道问题所在了。在 HikariCP isConnectionAlive 中,它会在调用setConnectionTestQuery 中的查询集之前尝试将网络超时设置为上面在setValidationTimeout 中指定的值。但是 JTDS 不支持java.sql.Connection.setNetworkTimeout,因此读取超时是操作系统的默认设置。大约需要 10 分钟。
理论上,您应该能够将驱动程序属性套接字超时设置为一种解决方法(尽管它对我不起作用)。但这不是一个很好的解决方法,因为您确实希望测试查询与实际查询的查询超时不同。
所以这不是 HikariCP 问题,而是 JTDS 问题。
【问题讨论】: