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에서 다양한 매개 변수를 시도했지만 아무런 차이가 없습니다.
데이터 소스 및 JdbcTemplate을 구성하고 삽입하는 위치에 구성을 표시하십시오. – skaffman