2009-03-16 4 views
5

c3p0의 ConnectionCustomizer을 사용하여 응용 프로그램에서 데이터베이스 연결의 생성과 제거를 기록하려고합니다. 이 코드에는 다음과 같은 코드가 있습니다.C3p0의 잠금 주문

log(C3P0Registry.getPooledDataSources()) 

교착 상태가 발생합니다. c3p0에 동기화 된 메서드를 사용하는 라이브러리의 객체가 두 개 이상 있고 의도 된 잠금 순서를 지정하지 않는 것 같습니다. 연결을 로그 할 때 C3P0Registry에 잠금 장치가 있고 결국에는 PoolBackedDataSource (단순히 데이터 소스 목록을 생성하면 잠금을 유발하는 해시 코드에 액세스하는 것입니다).

연결 제공자를 종료하면 (C3P0ConnectionProvider.close()) 잠금이 반대 순서로 호출됩니다. 그러나 자식 데이터 소스가 종료되는 동안 로깅이 트리거됩니다. 결과는 교착 상태입니다.

내가이 유효 예상 통화량 C3P0 라이브러리로 만드는 중이라서 모두 호출처럼 보인다 :

  • C3P0ConnectionProvider.close()
  • C3P0Registry.getPooledDataSources() 또한처럼 보인다

(명시 적으로 문서에 명시하지 않는 한) 자체의 잠금 전략을 관리하는 것은 도서관의 책임이어야합니다. (모범 사례에 대한 나의 이해를 확인하기 위해 누구에게 책임이 있다고 말하지 않습니다.)

이 문제는 어떻게 해결해야합니까? c3p0는보다 현대적인 메커니즘보다는 동기화 된 메소드를 사용하기 때문에 잠금을 실제로 테스트 할 수는 없습니다.

DataSource 마감 코드에서 C3P0Registry 잠금을 먼저 잡고 나서 DataSource을 닫을 수 있습니다. 올바른 잠금 순서를 추측 할 것입니다. 잠금 순서는 내가 편안하다고 느끼는지 모르겠습니다.

로깅 호출의 잠금 순서를 바꿀 수 있다고 생각하지 않습니다. DataSources의 목록을 얻으려면 C3P0Registry이 필요합니다. DataSources을 먼저 잠그지 않고 잠글 수 없으므로 C3P0Registry을 참조하십시오.

또 다른 해결책은 물론 c3p0 이상의 모든 상위 수준 잠금을 제공하는 것입니다. 연결 풀의 경우, 그 점을 무시하는 것 같습니다.

지금은 로깅을 롤백하고 있습니다. 어떤 도움을 주셔서 감사합니다.

+0

비슷한 것을 경험하고 이에 대한 자세한 정보를 찾았습니까? –

+0

close()를 호출하는 코드 주위에 동기화 된 블록을 추가하여 결국 로깅과 동일한 순서로 잠금을 얻게되었습니다. 그것은 지저분하지만 다시 C3p0의 잠금 전략도 마찬가지입니다. –

답변

0

잠금 문제를 해결하는 방법을 모릅니다. 그러나 여기에서 다시 한 걸음 뒤로 물러나서 원래 문제에 대해 생각해야합니다. "응용 프로그램에서 데이터베이스 연결의 생성 및 제거를 기록하려고합니다 ..."

나는 다음을 권장합니다.

클래스를 만들고 javax.sql.DataSource를 구현하도록합니다. 동일한 유형의 필드를 만들고 모든 메소드를 위임합니다. getConnection() 메소드에서 java.sql.Connection을 감싸는 자체 Connection 클래스를 리턴한다. 그런 다음이 클래스를 원래 데이터 소스 주위에 랩핑하십시오. 클래스에서 이제 간단하게 로거를 만들고 로그에 표시 할 모든 작업을 기록 할 수 있습니다.