2011-08-08 81 views
5

下面挂的是环境:JTDS插座与C3P0连接检查(SQL Server 2008 R2中)

  • Java 5的
  • 在Windows(不知道的版本)
  • 在Tomcat中运行6.0.18 Web应用程序
  • 数据库:SQL Server 2008 R2的
  • JDBC驱动程序:JTDS 1.2.5
  • 连接池提供商:C3P0 0.9.1.2

我正在尝试调试客户端遇到的问题。基本上每隔几周,我们的Web应用程序就会锁定在他们的服务器上,而且他们无法访问它。重新启动解决了这个问题。进一步的调查显示,所有事情都被锁定的原因是所有数据库连接都在等待返回。我认为这个问题很可能与SQL Server,而不是C3P0。

我相信这是C3P0的“空闲检查查询”挂起。查询是这样的:

select * from c3p0_connection_test_table 

它看起来像这样运行查询,并且永远不会返回结果。这是我在线程转储中看到的内容。通知DefaultConnectionTester.activeCheckConnection(),这是空闲检查:

"com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2" daemon prio=6 tid=0x0000000007c32000 nid=0x1250 runnable [0x000000001072f000] 
    java.lang.Thread.State: RUNNABLE 
    at java.net.SocketInputStream.socketRead0(Native Method) 
    at java.net.SocketInputStream.read(SocketInputStream.java:129) 
    at java.io.DataInputStream.readFully(DataInputStream.java:178) 
    at java.io.DataInputStream.readFully(DataInputStream.java:152) 
    at net.sourceforge.jtds.jdbc.SharedSocket.readPacket(SharedSocket.java:841) 
    at net.sourceforge.jtds.jdbc.SharedSocket.getNetPacket(SharedSocket.java:722) 
    - locked <0x000000016ac03f48> (a java.util.ArrayList) 
    at net.sourceforge.jtds.jdbc.ResponseStream.getPacket(ResponseStream.java:466) 
    at net.sourceforge.jtds.jdbc.ResponseStream.read(ResponseStream.java:103) 
    at net.sourceforge.jtds.jdbc.ResponseStream.peek(ResponseStream.java:88) 
    at net.sourceforge.jtds.jdbc.TdsCore.wait(TdsCore.java:3928) 
    at net.sourceforge.jtds.jdbc.TdsCore.executeSQL(TdsCore.java:1045) 
    - locked <0x000000016d965268> (a net.sourceforge.jtds.jdbc.TdsCore) 
    at net.sourceforge.jtds.jdbc.JtdsStatement.executeSQLQuery(JtdsStatement.java:465) 
    at net.sourceforge.jtds.jdbc.JtdsStatement.executeQuery(JtdsStatement.java:1301) 
    at com.mchange.v2.c3p0.impl.DefaultConnectionTester.activeCheckConnection(DefaultConnectionTester.java:73) 
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.testPooledConnection(C3P0PooledConnectionPool.java:374) 
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.refurbishIdleResource(C3P0PooledConnectionPool.java:310) 
    at com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask.run(BasicResourcePool.java:1999) 
    at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547) 

但是可能造成这样一个简单的查询,以从套接字读取挂?我不相信这个表上会有任何数据库锁定,因为它完全由C3P0管理,并且从不插入/更新。此外,任何尝试从池中获取连接的失败尝试(如果这是挂起的原因),我会希望在某处找到堆栈跟踪。相反,我看到的应用程序只是锁定,因为所有未来的连接请求都在等待这个“空闲检查”来完成。

这里是等待“空闲检查”的一个线程来完成:

"http-80-3" daemon prio=6 tid=0x0000000007c33800 nid=0x122c in Object.wait() [0x000000001082d000] 
    java.lang.Thread.State: WAITING (on object monitor) 
    at java.lang.Object.wait(Native Method) 
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:579) 
    - locked <0x0000000167a88a60> (a com.mchange.v2.resourcepool.BasicResourcePool) 
    at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource(BasicResourcePool.java:477) 
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:525) 
    at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:128) 
    at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection(LocalDataSourceConnectionProvider.java:81) 
    at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446) 
    at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167) 
    at org.hibernate.jdbc.JDBCContext.connection(JDBCContext.java:142) 
    at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:85) 
    at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1354) 
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:555) 
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371) 
    at sun.reflect.GeneratedMethodAccessor105.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
    at $Proxy15.getTransaction(Unknown Source) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:317) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:105) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
    at $Proxy79.getCrowdProperties(Unknown Source) 
    at com.jamasoftware.contour.gateway.crowd.CrowdSsoServices.autoLogin(Unknown Source) 
    at com.jamasoftware.contour.security.AutoLoginServicesManager.autoLogin(Unknown Source) 
    at org.springframework.security.ui.rememberme.RememberMeProcessingFilter.doFilterHttp(RememberMeProcessingFilter.java:74) 
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53) 
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
    at org.springframework.security.ui.AbstractProcessingFilter.doFilterHttp(AbstractProcessingFilter.java:277) 
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53) 
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
    at com.jamasoftware.contour.view.filter.CheckSetupFilter.doFilter(Unknown Source) 
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
    at org.springframework.security.context.HttpSessionContextIntegrationFilter.doFilterHttp(HttpSessionContextIntegrationFilter.java:235) 
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53) 
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
    at org.springframework.security.concurrent.ConcurrentSessionFilter.doFilterHttp(ConcurrentSessionFilter.java:99) 
    at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53) 
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) 
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
    at com.jamasoftware.contour.view.filter.ExpirationFilter.doFilter(Unknown Source) 
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
    at com.jamasoftware.contour.view.filter.GzipFilter.doFilter(Unknown Source) 
    at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390) 
    at org.springframework.security.util.FilterChainProxy.doFilter(FilterChainProxy.java:175) 
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237) 
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167) 
    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.core.StandardHostValve.invoke(StandardHostValve.java:127) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298) 
    at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:864) 
    at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:579) 
    at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1665) 
    at java.lang.Thread.run(Thread.java:619) 

通过观察C3P0的源代码,这两条线在顶部:

at java.lang.Object.wait(Native Method) 
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:579) 

......仅在连接等待“空闲检查”时发生。

不幸的是,这是一个客户端,我不能在这里报告环境的确切细节。但我可以在下一次电话会议上向他们提出任何建议。

UPDATE

该申请于今日再次锁定。以下是我们迄今尝试过的东西:

  • 他们已经更新到最新的jTDS驱动程序(1.2。5)
  • 我已经设置在连接字符串到300 socketTimeout财产,但仍司机长5分钟后被困在socketRead0()保持
  • 我们从“SELECT * FROM c3p0_connection_test_table”到“选择更改活动检查查询1"
  • 我们增加了unreturnedConnectionTimeoutdebugUnreturnedConnectionStackTraces属性C3P0(这些都没有赶上断开的连接,虽然)

这里都是我们设置了C3P0连接属性:

<property name="minPoolSize" value="1"/> 
    <property name="maxPoolSize" value="30"/> 
    <property name="acquireIncrement" value="3"/> 
    <property name="automaticTestTable" value="c3p0_connection_test_table"/> 
    <property name="idleConnectionTestPeriod" value="30"/> 
    <property name="testConnectionOnCheckin" value="true"/> 
    <property name="testConnectionOnCheckout" value="true"/> 

发生的一件奇怪的事情是,当应用程序被锁定时,我们试图用应用程序用户登录到SQL Server Management Studio,它不会让我们进入(我认为这只是一个正常的超时错误)。数据库已启动并在端口1433上侦听(通过telnet进行验证),所以我认为这意味着已达到数据库的最大连接数。不过,我不确定这是否有助于确定此问题的原因。

信息随后没有成功

  • This person曾与操作系统的问题,以及潜在的NIC卡的服务器上的数字
  • 下面的回答者指出我的错误在旧版本jTDS here

有用的答案可以要求我检查客户机器上的某些东西,或者指出可能的根本原因。无论答案如何帮助我追踪下来,都可以获得赏金。

回答

2

第一个想法:检查他们使用的是最新的jTDS版本,并且SQL Server被修补并更新到最新的SP!

在jTDS缺陷跟踪中,有一些关于这种行为的报告,最值得注意的是this one。显然,SQL Server正在关闭连接,但jTDS没有注意到。

在JTDS的新版本有一个socketTimeoutproperty(默认值= 0),这也许会有所帮助。

您也可以测试不同的JDBC驱动程序。

+0

很好的建议,谢谢。当我在不久之后与他们见面时,我会研究这些问题,并用任何新的细节更新这个问题。 –

+0

他们正在使用最新的jTDS(1.2.5),而SQL Server似乎是最新SP(SQL Server 2008 RC2)的一个非常流行的安装。我让他们添加了socketTimeout属性(我们将其设置为非常高的300或5分钟),但他们仍然最终再次出现此问题。 –

+0

@SeanA:1. socketTimeout的值越高,jTDS实现连接所用的时间就越长(loginTimeout也一样)。 2.由于您提到无法使用Management Studio进行连接,因此我不知道每个用户配置的最大连接数是多少。 3.如R2中的RC2? 4.你不打算从M $寻求支持吗? 5.您在本地连接,您是否使用本地主机服务器地址? – Vlad

0

我遇到了类似的问题,使用jtds连接到sql server时挂起了c3p0(0.9.1)。

我解决了这个问题,不使用c3p0,只需要使用DriverManager打开一个连接。我相信它不是表现力,但它的工作原理。

1

在SQL Server检查 - 属性 - 连接 - “使用查询调控,以防止长时间运行的查询”已禁用

0

当时还存在另一个线程关闭,而连接的连接正在测试?貌似C3P0固定这c3p0-0.9.2-PRE3:

- 要求PooledConnections的测试,以自己的相关 与 PooledConnections锁,以防止偶尔死锁时的PooledConnection。关闭() 与Connection测试一致。非常感谢一位匿名SourceForge用户 呼吁关注此问题。

来自:https://github.com/swaldman/c3p0/blob/master/src/dist-static/CHANGELOG