c3p0连接池是否确保最大池大小?

时间:2013-06-05 06:19:05

标签: datasource connection-pooling c3p0

我已经经历了几个问题,this有点相关,但没有回答我的问题。

c3p0连接池maxPoolSize是否确保某个时间的连接数永远不会超过此限制?如果maxPoolSize=5和10个用户同时开始使用该应用程序会怎样?

我的应用。构造

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass"><value>${database.driverClassName}</value>/property>
        <property name="jdbcUrl"><value>${database.url}</value></property>
        <property name="user"><value>${database.username}</value></property>
        <property name="password"><value>${database.password}</value></property>
        <property name="initialPoolSize"><value>${database.initialPoolSize}</value>/property>
        <property name="minPoolSize"><value>${database.minPoolSize}</value></property>
        <property name="maxPoolSize"><value>${database.maxPoolSize}</value></property>
        <property name="idleConnectionTestPeriod"><value>200</value></property>
        <property name="acquireIncrement"><value>1</value></property>
        <property name="maxStatements"><value>0</value></property> 
        <property name="numHelperThreads"><value>3</value></property>
    </bean>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>              
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
        <property name="dataSource" ref="dataSource"/>
    </bean>

1 个答案:

答案 0 :(得分:14)

区分DataSource和连接池非常重要。

maxPoolSize由c3p0在 per-pool 的基础上强制执行。但是单个DataSource可能拥有多个连接池,因为每组身份验证凭据都有(并且必须是)一个不同的池。如果只调用默认的dataSource.getConnection()方法,则maxPoolSize将是池获取和管理的最大连接数。但是,如果使用dataSource.getConnection( user, password )获取Connections,则DataSource最多可以保留(maxPoolSize * num_distinct_users)个连接。

回答您的具体问题,如果maxPoolSize为5,并且10个客户端同时命中c3p0数据源,则最多不会有5个客户端获得连接。其余客户端将wait(),直到返回Connections(或c3p0.checkoutTimeout已过期)。

一些警告:c3p0强制执​​行maxPoolSize,如上所述。但是,即使只使用一个每个身份验证池,也无法保证您不会偶尔看到超过maxPoolSize个连接已签出。例如,c3p0过期并异步销毁Connections。就c3p0而言,一旦Connection对客户端不可用并标记为销毁,而不是实际被销毁时​​,Connection就会消失。因此,如果maxPoolSize为5,则有可能偶尔会在数据库中观察到6个打开的连接。池中有5个连接处于活动状态,而第6个连接处于排队状态但尚未销毁。

另一种情况是,如果在运行时修改连接池属性,则可能会意外地看到许多连接打开。实际上,内部连接池的配置是不可变的。当您在运行时“更改”池参数时,实际发生的是使用新配置启动新池,并将旧池置于“放空”模式。从旧池中检出的连接保持有效,但是当它们签入时,它们将被销毁。只有在重新检入所有旧池连接后,池才真正死了。

所以,如果您有一个已签出maxPoolSize Connections的池,然后更改配置参数,您可能会暂时看到最高为(2 * maxPoolSize)的峰值,如果新池被批量命中已返回从旧池中检出Connections的连接之前的流量。在实践中,这很少是一个问题,因为动态重新配置并不常见,并且连接检查应该并且通常非常简短,因此旧池连接快速消失。但它可能会发生!

我希望这会有所帮助。

ps acquireIncrement最好设置大于1的值。acquireIncrement为1意味着没有连接在需求之前被预取,因此每当负载增加时,某些线程将直接遇到连接获取的延迟。