【问题标题】:Does c3p0 connection pooling ensures max pool size?c3p0 连接池是否确保最大池大小?
【发布时间】:2013-05-31 17:38:42
【问题描述】:

我已经解决了几个问题,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>

【问题讨论】:

    标签: datasource connection-pooling c3p0


    【解决方案1】:

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

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

    为了回答您的具体问题,如果maxPoolSize 是 5 并且 10 个客户端同时访问 c3p0 数据源,那么其中不超过 5 个将首先获得连接。其余客户端将wait() 直到连接返回(或c3p0.checkoutTimeout 已过期)。

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

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

    所以,如果您有一个池已检出 maxPoolSize 连接,然后更改配置参数,如果新池在连接之前遇到大量流量,您可能会暂时看到高达 (2 * maxPoolSize) 的峰值退房的旧游泳池已经退回。实际上,这很少会成为问题,因为动态重新配置并不常见,并且连接检查应该而且通常非常简短,因此旧池连接会迅速消失。但它可能发生!

    我希望这会有所帮助。

    ps acquireIncrement 最好设置大于 1 的值。acquireIncrement 为 1 表示没有提前预取连接,因此当负载增加时,一些线程将直接经历连接获取的延迟。

    【讨论】:

    • 所以如果我使用 Guice 创建数据源(我假设这不是在运行时),将 maxpoolsize 配置为 100(仅使用 getConnection()),我总共有 10 个主机服务。这是否意味着与数据库的最大连接数为 10*100?我在pg_stat_activity 中看到的空闲连接数(运行SELECT 1SHOW TRANSACTION ISOLATION LEVEL)要多得多,这正常吗?
    • 只有 10 个数据源使用默认身份验证,maxPoolSize 为 100,您的应用程序通常在服务器端使用不超过 1000 个连接。它可能会暂时超过这个值,因为连接是异步的close()ed。但如果它确实显着地或永久地超过了这个值,你就需要解释一下。
    • 也许是最常见的问题,导致连接数比预期多很多倍,不尊重池的预期生命周期。是 Guice 还是在您的应用程序的生命周期中初始化 DataSource 一次(好),还是为每个客户端构建一个新的 DataSource(非常非常糟糕)。如果生命周期没问题,您可能需要检查您的设置:您是否正在快速使用 Connections?另外,请考虑尝试更大的numHelperThreads,这样线程池中的异步 Connection close() 就不太可能落后。
    猜你喜欢
    • 2017-06-19
    • 1970-01-01
    • 2011-08-13
    • 1970-01-01
    • 2012-09-07
    • 1970-01-01
    • 1970-01-01
    • 2013-02-03
    • 2012-07-06
    相关资源
    最近更新 更多