1

我正在尝试在 Spring 应用程序中使用 BasicDataSource 与 JDBCTemplate 连接池。从我读过的所有内容来看,这应该非常简单:只需在 XML 中配置 BasicDataSource,将数据源注入 bean,然后在 setter 方法中创建一个新的 JDBCTemplate。

当我这样做时,我注意到我的表现很糟糕。所以后来我切换到 Spring 的 SingleConnectionDataSource,只是想看看会发生什么,我的性能变得更好了。我开始使用分析器工具进行调查,我注意到在使用 BasicDataSource 时,会为每个查询创建一个新连接。

进一步调查,我可以看到查询完成后连接在哪里关闭。特别是在 Spring 的 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() 方法只会将连接返回到池中。但是,当我查看探查器中发生的情况时,实际上是在我的 sybase 连接上调用了 close 方法:不是我希望看到的任何类型的“池化连接包装器”。

最后一件事(这是我现在要研究的内容):我对一些查询使用 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 秒。我在 BasicDataSource 上尝试了各种参数,例如设置 maxActive=1 和 testOnBorrow=false,但没有任何区别。

4

1 回答 1

0

我认为我的问题是我的 sybase 的 jdbc 库已经过时了。

于 2013-04-01T13:42:14.927 回答