2012-03-20 5 views
1

Spring 애플리케이션에서 JDBCTemplate을 사용하여 연결을 풀링하기 위해 BasicDataSource를 사용하려고합니다. 필자가 읽은 모든 것에서이 작업은 매우 간단합니다. XML로 BasicDataSource를 구성하고 데이터 소스를 bean에 주입 한 다음 setter 메서드에서 새 JDBCTemplate을 만듭니다.JDBCTemplate이있는 BasicDataSource가 연결을 예상대로 풀링하지 않습니다.

내가 이것을했을 때, 나는 내 공연이 끔찍하다는 것을 알았다. 그래서 저는 Spring의 SingleConnectionDataSource로 바꿨습니다. 무슨 일이 일어날 지 알았고, 성능은 이 훨씬 더이되었습니다. 프로파일 러 도구로 조사하기 시작했고, BasicDataSource를 사용할 때 모든 쿼리에 대해 새로운 연결이 만들어지고 있음을 발견했습니다.

더 자세히 살펴보면 쿼리가 끝난 후 연결이 닫히는 것을 볼 수 있습니다. 특히 봄의 DataSourceUtil 클래스 :

public static void doReleaseConnection(Connection con, DataSource dataSource) throws SQLException { 
    if (con == null) { 
     return; 
    } 

    if (dataSource != null) { 
     ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource); 
     if (conHolder != null && connectionEquals(conHolder, con)) { 
      // It's the transactional Connection: Don't close it. 
      conHolder.released(); 
      return; 
     } 
    } 

    // Leave the Connection open only if the DataSource is our 
    // special SmartDataSoruce and it wants the Connection left open. 
    if (!(dataSource instanceof SmartDataSource) || ((SmartDataSource) dataSource).shouldClose(con)) { 
     logger.debug("Returning JDBC Connection to DataSource"); 
     con.close(); 
    } 
} 

나는 열려있는 연결을 남긴다 '한 SmartDataSource'에 대한 특별한 논리가 예고 한 것. 이는 내가 보던 동작을 부분적으로 설명합니다. SingleConnectionDataSource가 SmartDataSource를 구현하기 때문에 연결이 닫히지 않습니다. 그러나 BasicDataSource를 사용하여 연결의 close() 메서드가 연결을 풀로 반환한다고 생각했습니다. 그러나 프로파일 러에서 무슨 일이 일어나고 있는지 살펴볼 때 close 메소드는 실제로 sybase 연결에서 호출됩니다. 실제로 볼 수있는 'Pooled Connection Wrapper'가 아닙니다.

마지막으로 한 가지 (이제 조사 할 내용입니다) : 일부 쿼리 (데이터베이스 커밋 포함)에 TransactionTemplate을 사용하지만 간단한 쿼리는 transactionTemplate 내부에 없습니다. 그게 문제와 관련이 있는지 없는지 나는 모른다.

편집 1 :

확인은 마침내 여기 여기

public class DBConnectionPoolTest { 

@Autowired 
@Qualifier("myDataSource") 
private DataSource dataSource; 

@Test 
public void test() throws Exception{ 
    JdbcTemplate template = new JdbcTemplate(dataSource); 
    StopWatch sw = new StopWatch(); 
    sw.start(); 
    for(int i=0; i<1000; i++){ 
     template.queryForInt("select count(*) from mytable"); 
    } 
    sw.stop(); 

    System.out.println("TIME: " + sw.getTotalTimeSeconds() + " seconds"); 
}} 

내 두 가지 문제를 보여줍니다 아주 간단한 테스트는 프로젝트를 조금 뽑아지고 후에 조사하는 좀 더 시간을 가지고 및 데이터 소스 구성 :

<bean id="myDataSource" class="org.springframework.jdbc.datasource.SingleConnectionDataSource"> 
    <property name="driverClassName" value="${db.driver}" /> 
    <property name="url" value="${db.url}" /> 
    <property name="username" value="${db.username}" /> 
    <property name="password" value="${db.password}" /> 
</bean> 

<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"> 
    <property name="driverClassName" value="${db.driver}" /> 
    <property name="url" value="${db.url}" /> 
    <property name="username" value="${db.username}" /> 
    <property name="password" value="${db.password}" /> 
</bean> 

첫 번째 구성으로 테스트를 실행하면 약 2.1 초가 소요됩니다. 두 번째 구성으로 실행할 때 약 4.5 초가 걸립니다. maxActive = 1 및 testOnBorrow = false 설정과 같은 BasicDataSource에서 다양한 매개 변수를 시도했지만 아무런 차이가 없습니다.

+0

데이터 소스 및 JdbcTemplate을 구성하고 삽입하는 위치에 구성을 표시하십시오. – skaffman

답변

0

필자의 경우 문제는 sybase 용 jdbc 라이브러리가 구형이라고 생각합니다.