2013-06-05 123 views
5

我已经经历了几个问题,this有点相关但不回答我的问题。c3p0连接池是否可确保最大池大小?

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> 

回答

11

区分数据源和连接池很重要。

maxPoolSize由c3p0在每池的基础上强制执行。但是单个数据源可能拥有多个连接池,因为每个认证证书集都有一个独立的池(并且必须)。如果仅调用默认的dataSource.getConnection()方法,则maxPoolSize将是池获取和管理的最大连接数。但是,如果使用dataSource.getConnection(user, password)获取连接,则DataSource可能会保留最多(maxPoolSize * num_distinct_users)连接。

回答你的具体问题,如果maxPoolSize是5和10个客户端同时点击一个c3p0数据源,其中不超过5个将首先得到连接。剩余的客户端将为wait(),直到返回连接(或c3p0.checkoutTimeout已过期)。

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

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

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

我希望这可以帮助。

ps acquireIncrement最好设置大于1的值。acquireIncrement为1意味着没有连接在需求提前预取,所以无论何时加载一些线程将直接经历连接获取的延迟。