2012-10-16 3 views
3

는 유휴 연결을 dropps 또는 DB가 다운되어 다시 내 웹 애플리케이션에서 다음과 같은 오류 메시지가 표시됨 :이 내가Guice JPA - "이 연결이 닫혔습니다." DB 후 오류

SQL Error: 0, SQLState: 08006 - An I/O error occured while sending to the backend. 

하지만 그 후 얻을 시작되면

javax.persistence.PersistenceException: org.hibernate.exception.JDBCConnectionException: could not inspect JDBC autocommit mode 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1365) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1293) 
    at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:265)  
... 60 more 
Caused by: org.hibernate.exception.JDBCConnectionException: could not inspect JDBC autocommit mode 
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:131) 
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49) 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125) 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110) 
    at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.isAutoCommit(LogicalConnectionImpl.java:395) 
    at org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl.afterNonTransactionalQuery(TransactionCoordinatorImpl.java:195) 
    at org.hibernate.internal.SessionImpl.afterOperation(SessionImpl.java:565) 
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1220) 
    at org.hibernate.internal.QueryImpl.list(QueryImpl.java:101) 
    at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:256) 
... 70 more 
Caused by: org.postgresql.util.PSQLException: This connection has been closed. 
    at org.postgresql.jdbc2.AbstractJdbc2Connection.checkClosed(AbstractJdbc2Connection.java:712) 
    at org.postgresql.jdbc2.AbstractJdbc2Connection.getAutoCommit(AbstractJdbc2Connection.java:678) 
    at sun.reflect.GeneratedMethodAccessor138.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:601) 
    at org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:126) 
    at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:99) 
    at org.apache.tomcat.jdbc.pool.DisposableConnectionFacade.invoke(DisposableConnectionFacade.java:63) 
    at $Proxy66.getAutoCommit(Unknown Source) 
    at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.isAutoCommit(LogicalConnectionImpl.java:392) 

을 단지 :

SQL Error: 0, SQLState: 08003 - This connection has been closed. 

문제는 다음과 같습니다. testOnBorrow를 설정 했으므로 열려있는 연결 만 얻을 것으로 예상됩니다.

만약 도움이된다면 : pool ususaly는 양호한 연결과 나쁜 연결이 혼합되어 있으며 시간이 지남에 따라 문제가 해결 된 것 같지만 서버가 12 시간 이상 가동되어 여전히 잘못된 연결이 반환되었습니다. 다시 시작한 후 모든 시간이 정상적으로 작동합니다.

문제를 좀 더 디버깅했으며 풀이 잘못된 연결을 반환하는 것처럼 보입니다. DB에서 모든 연결을 종료 한 후에 다음을 얻습니다.

SQL Error: 0, SQLState: 57P01 

그런 다음 일반적으로 삭제 된 연결이 풀에서 반환됩니다. 질문 : 응용 프로그램 문제입니까?

JMX를 통해 풀을 제거하려고했지만 그 효과가없는 것 같습니다. 또 다른 이상한 점은 앱이 분명히 아무 것도하지 않는다고해도 (스레드 덤프를 통해 확인) JMX 빈은 7 개의 활성 연결과 0 개의 유휴 연결을 보여줍니다. DB 액세스를 요구하는 요청을 실행하면 즉각적으로 응답을 받지만 (유휴 연결을 사용할 수 없음), JMX는 그 후에 7 개의 활성 연결과 0 개의 유휴 연결을 보여줍니다.

추신. 어쩌면 나는 명백한 무언가를 놓치고 있는데 이것이 내 문제인 연결 관리 문제 일까? persistence.xml을 통해 구성된 JPA EntityManager를 사용하고 있습니다. 어쩌면 내가 잘못하고있는 중이고 연결이 사용 후 제대로 닫히지 않았습니다 (반환 된)?

+0

방법이 오류를 해결 했습니까? –

답변

5

실제로 응용 프로그램 오류가 의심 될 때 나는 옳았습니다. JpaPersistService를 사용하는 경우 당신은 Guice는 자동으로 당신을 위해 일을 시작, 활성의 UnitOfWork 외부의 EntityManager를 액세스하려고하면

그것은 모든 좋게, Issue 730: Automatically started UnitOfWork is never ended

에서 설명한 기능입니다. 그러나, Guice는 (그리고 can not)이 UnitOfWork를 언제 끝내야하는지 알지 못하기 때문에 결코 그렇게하지 않습니다.

결과? 문제가되는 스레드는 응용 프로그램의 수명이 끝날 때까지 동일한 EntityManager 으로 멈 춥니 다. 이것은 응용 프로그램이 실행될 수없는 나쁜 상태이며 잠시 후 사용 가능한 메모리가 소모되어 충돌합니다.

여기서 진짜 살인자는 을 실수했을 때 분명하지 않다는 것입니다. 유일한 실제 팁은 ( EM의 첫 번째 레벨 캐시로 인해) 서로 다른 스레드 사이에서 데이터베이스의 데이터가 일치하지 않거나 응용 프로그램 메모리 사용량이 증가하는 것입니다 ( ). 내 경우에는 의심스럽지 않은 액티브 연결이 있었고, 자세한 로깅을 켰을 때 앱이 풀에서 연결을 빌리는 것이 아니라 이미 연결된 연결을 재사용하고있는 것으로 나타났습니다 닫히지 않은 EntityManager에 의해.

사실이 문제의 꽤 중복보고있다 : http://code.google.com/p/google-guice/issues/list?can=1&q=UnitOfWork

0

META-INF/context.xmlvalidationQuery이 포함되도록 수정 한 경우 Tomcat은 conf/engine/host/webapp.xml 아래의 이전 정의를 캐싱 할 가능성이 큽니다. Tomcat을 종료하고 해당 파일을 제거한 다음 Tomcat을 다시 시작합니다. Tomcat이 다운되었을 때 work 디렉토리를 삭제해도 괜찮습니다.

+0

나는 그것을 생각하지 않는다 - 그것은 여러 서버에서 여러 번 발생했다 (다시 시작 함). 또한 초기 배포 이후 validationQuery를 수정하지 않았습니다. –

5

와일드 샷 : 코드 herevalidationIntervaltestOnBorrow인지 확인합니다.

이 값을 30 초 기본값에서 5 분으로 설정 했으므로 DB가 연결을 끊은 후 5 분 동안은 여전히 ​​부실 연결이 발생할 수 있습니다. DB 시간 초과가 5 분 미만이면 ... 불행.

이 이론을 테스트하기 위해 validationInterval을 우스운 값으로 설정할 수 있습니다.

도움이된다면 (읽기 : 우리는 오른쪽 손잡이를 찾았습니다.) DB 시간 초과보다 더 짧은 시간에 설정해야합니다. 따라서 DB가 유휴 연결을 끊기로 결정하면 validationInterval은 다음 차용 전에 연결이 확인되도록합니다. DB 서버 재시작 (즉, 제한 시간 없음)으로 인한 폐쇄 연결은이 솔루션의 영향을받지 않지만 적어도 정상 상태로 돌아 오는 시간은 더 낮습니다.

참고 : 방금 Google에 코드를 요청했습니다. 이 코드가 실제 코드인지 고대 코드인지는 알 수 없습니다.

+0

[실제 Tomcat 소스] (http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/) pool/PooledConnection.java? view = markup)은 SpringSource의 복사본을 보는 대신 사용할 수 있습니다. –

+0

@A.H처럼 보입니다. 올바른 경로에있을 가능성이 높습니다. 유효성 검사 간격은 적어도 Tomcat의 jdbc-pool을 사용할 때 validate-on-borrow에 적용됩니다. –

+0

그런 소란 스럽군요.하지만 나도 그렇게 생각하지 않아. 서버를 12 시간 이상이 상태에서 실행하고 스크립트를 10 분마다 호출하도록했습니다. 전체 시간 동안 매시 2 또는 3 개의 오류가 발생했습니다. 여전히 낮은 값을 설정하고 어떤 결과가 나타나는지 확인하려고 노력할 것입니다. –