每隔一段时间我就不得不维持一个旧的Java来停止响应。我设法获得了几个线程堆栈跟踪,大多数线程被阻止,试图获得连接:
"tomcat-http-8180-168" - Thread t@10137
java.lang.Thread.State: BLOCKED
at oracle.jdbc.pool.OracleImplicitConnectionCache.retrieveCacheConnection(OracleImplicitConnectionCache.java:566)
- waiting to lock <566080> (a oracle.jdbc.pool.OracleImplicitConnectionCache) owned by "Thread-6" t@29
持有锁的线程显示:
"Thread-6" - Thread t@29
java.lang.Thread.State: BLOCKED
at oracle.jdbc.driver.PhysicalConnection.closeLogicalConnection(PhysicalConnection.java:3849)
- waiting to lock <146da30> (a oracle.jdbc.driver.T4CConnection) owned by "tomcat-http-8180-369" t@17665
at oracle.jdbc.driver.LogicalConnection.cleanupAndClose(LogicalConnection.java:304)
at oracle.jdbc.pool.OracleImplicitConnectionCache.closeCheckedOutConnection(OracleImplicitConnectionCache.java:1392)
at oracle.jdbc.pool.OracleImplicitConnectionCacheThread.runAbandonedTimeout(OracleImplicitConnectionCacheThread.java:250)
- locked <566080> (a oracle.jdbc.pool.OracleImplicitConnectionCache)
at oracle.jdbc.pool.OracleImplicitConnectionCacheThread.run(OracleImplicitConnectionCacheThread.java:81)
此线程似乎负责关闭已放弃的连接,并且它本身被阻止等待其他线程完成:
"tomcat-http-8180-369" - Thread t@17665
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at oracle.net.ns.Packet.receive(Packet.java:282)
at oracle.net.ns.DataPacket.receive(DataPacket.java:103)
at oracle.net.ns.NetInputStream.getNextPacket(NetInputStream.java:230)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:175)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:100)
at oracle.net.ns.NetInputStream.read(NetInputStream.java:85)
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.readNextPacket(T4CSocketInputStreamWrapper.java:122)
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.read(T4CSocketInputStreamWrapper.java:78)
at oracle.jdbc.driver.T4CSocketInputStreamWrapper.readB1(T4CSocketInputStreamWrapper.java:149)
at oracle.jdbc.driver.T4CMAREngine.buffer2Value(T4CMAREngine.java:2393)
at oracle.jdbc.driver.T4CMAREngine.unmarshalSB8(T4CMAREngine.java:1401)
at oracle.jdbc.driver.T4C8TTILob.readRPA(T4C8TTILob.java:837)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:292)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
at oracle.jdbc.driver.T4C8TTIClob.read(T4C8TTIClob.java:240)
at oracle.jdbc.driver.T4CConnection.getChars(T4CConnection.java:3015)
- locked <146da30> (a oracle.jdbc.driver.T4CConnection)
at oracle.sql.CLOB.getChars(CLOB.java:402)
at oracle.jdbc.driver.OracleClobReader.needChars(OracleClobReader.java:187)
at oracle.jdbc.driver.OracleClobReader.read(OracleClobReader.java:142)
at java.io.Reader.read(Reader.java:123)
at oracle.jdbc.driver.ClobAccessor.getString(ClobAccessor.java:291)
at oracle.jdbc.driver.T4CClobAccessor.getString(T4CClobAccessor.java:481)
at oracle.jdbc.driver.OracleResultSetImpl.getString(OracleResultSetImpl.java:1251)
- locked <146da30> (a oracle.jdbc.driver.T4CConnection)
at oracle.jdbc.driver.OracleResultSet.getString(OracleResultSet.java:494)
这最后一个线程正在运行一个繁重的查询。这也是为什么它被认为是被放弃而且Tomcat试图关闭它的原因,但它似乎不能正在使用并且有锁定。
我不明白为什么:
因为通过查看上面的线程堆栈,它发生了什么。当超长查询完成时(我知道我必须查看该查询)然后应用程序在线程解除阻塞后再次开始响应。
这是Tomcat的(v6)池配置(省略了敏感细节):
<Resource
name="jdbc/MainDBPool"
AutoCommit="true"
defaultReadOnly="false"
driverClassName="oracle.jdbc.OracleDriver"
factory="oracle.jdbc.pool.OracleDataSourceFactory"
fairQueue="false"
initialSize="10"
jdbcInterceptors="ConnectionState;StatementFinalizer"
jmxEnabled="true"
logAbandoned="false"
maxActive="100"
maxIdle="75"
maxWait="30000"
minEvictableIdleTimeMillis="5000"
minIdle="10"
removeAbandoned="true"
removeAbandonedTimeout="60"
testOnBorrow="false"
testOnReturn="false"
testWhileIdle="false"
timeBetweenEvictionRunsMillis="5000"
type="oracle.jdbc.pool.OracleDataSource"
connectionCachingEnabled="true"
connectionCacheName="tomcatConnectionCache1"
fastConnectionFailoverEnabled="true"
implicitCachingEnabled="true"
connectionCacheProperties="(ValidateConnection=true, PropertyCheckInterval=60, AbandonedConnectionTimeout=300, InitialLimit=10, MinLimit=30, MaxLimit=200, ConnectionWaitTimeout=30, InactivityTimeout=300)"
useEquals="false"
validationInterval="30000"
/>
我还研究了其他可能的原因,比如一个很长的完整GC,但启用了GC记录,并且没有很长的停顿可以解释这一点。
提前致谢。
答案 0 :(得分:0)
不支持Oracle隐式连接缓存。您必须使用通用连接池(UCP),它是ICC的替代品。您可以下载ucp.jar并查看"UCP with Tomcat"白皮书了解详情。