2012-10-16 51 views
2

我有以下代碼的PostgreSQL +休眠+ C3P0 = FATAL:對不起,太多的客戶已經

Configuration config = new Configuration().configure(); 
    config.buildMappings(); 
    serviceRegistry = new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry(); 
    SessionFactory factory = config.buildSessionFactory(serviceRegistry); 
    Session hibernateSession = factory.openSession(); 
    Transaction tx = hibernateSession.beginTransaction(); 
    ObjectType ot = (ObjectType)hibernateSession.merge(someObj); 
    tx.commit(); 
    return ot; 

hibernate.cfg.xml包含:

<session-factory> 

    <property name="connection.url">jdbc:postgresql://127.0.0.1:5432/dbase</property> 
    <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property> 
    <property name="connection.driver_class">org.postgresql.Driver</property> 

    <property name="connection.username">username</property> 
    <property name="connection.password">password</property> 

    <property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>   
    <property name="hibernate.c3p0.acquire_increment">1</property> 
    <property name="hibernate.c3p0.min_size">5</property> 
    <property name="hibernate.c3p0.max_size">20</property> 
    <property name="hibernate.c3p0.max_statements">50</property> 
    <property name="hibernate.c3p0.timeout">300</property> 
    <property name="hibernate.c3p0.idle_test_period">3000</property> 
    <property name="hibernate.c3p0.acquireRetryAttempts">1</property> 
    <property name="hibernate.c3p0.acquireRetryDelay">250</property> 

    <property name="hibernate.show_sql">true</property> 
    <property name="hibernate.use_sql_comments">true</property> 

    <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property> 
    <property name="hibernate.current_session_context_class">thread</property> 

    <mapping class="...." /> 

</session-factory> 

後幾秒鐘和一些成功的插入,以下除外離子出現:

org.postgresql.util.PSQLException: FATAL: sorry, too many clients already 
    at org.postgresql.core.v3.ConnectionFactoryImpl.doAuthentication(ConnectionFactoryImpl.java:291) 
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:108) 
    at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:66) 
    at org.postgresql.jdbc2.AbstractJdbc2Connection.<init>(AbstractJdbc2Connection.java:125) 
    at org.postgresql.jdbc3.AbstractJdbc3Connection.<init>(AbstractJdbc3Connection.java:30) 
    at org.postgresql.jdbc3g.AbstractJdbc3gConnection.<init>(AbstractJdbc3gConnection.java:22) 
    at org.postgresql.jdbc4.AbstractJdbc4Connection.<init>(AbstractJdbc4Connection.java:30) 
    at org.postgresql.jdbc4.Jdbc4Connection.<init>(Jdbc4Connection.java:24) 
    at org.postgresql.Driver.makeConnection(Driver.java:393) 
    at org.postgresql.Driver.connect(Driver.java:267) 
    at com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:135) 
    at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:182) 
    at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:171) 
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:137) 
    at com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1014) 
    at com.mchange.v2.resourcepool.BasicResourcePool.access$800(BasicResourcePool.java:32) 
    at com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask.run(BasicResourcePool.java:1810) 
    at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547) 
12:24:19.151 [   Thread-160] WARN     internal.JdbcServicesImpl - HHH000342: Could not obtain connection to query metadata : Connections could not be acquired from the underlying database! 
12:24:19.151 [   Thread-160] INFO        dialect.Dialect - HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect 
12:24:19.151 [   Thread-160] INFO     internal.LobCreatorBuilder - HHH000422: Disabling contextual LOB creation as connection was null 
12:24:19.151 [   Thread-160] INFO  internal.TransactionFactoryInitiator - HHH000268: Transaction strategy: org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory 
12:24:19.151 [   Thread-160] INFO    ast.ASTQueryTranslatorFactory - HHH000397: Using ASTQueryTranslatorFactory 
12:24:19.151 [   Thread-160] INFO      hbm2ddl.SchemaUpdate - HHH000228: Running hbm2ddl schema update 
12:24:19.151 [   Thread-160] INFO      hbm2ddl.SchemaUpdate - HHH000102: Fetching database metadata 
12:24:19.211 [Runner$PoolThread-#0] WARN    resourcepool.BasicResourcePool - [email protected] -- Acquisition Attempt Failed!!! Clearing pending acquires. While trying to acquire a needed new resource, we failed to succeed more than the maximum number of allowed acquisition attempts (1). Last acquisition attempt exception: 
org.postgresql.util.PSQLException: FATAL: sorry, too many clients already 
    at org.postgresql.core.v3.ConnectionFactoryImpl.doAuthentication(ConnectionFactoryImpl.java:291) 

看起來,休眠並沒有實現連接。但hibernateSession.close()會導致異常Session is closed,因爲調用了tx.commit()

回答

1

我發現原因爲什麼c3p0表現這種方式。這個問題是相當微不足道的...... 此部分代碼:

Configuration config = new Configuration().configure(); 
config.buildMappings(); 
serviceRegistry = new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry(); 
SessionFactory factory = config.buildSessionFactory(serviceRegistry); 

已執行多次。謝謝史蒂夫的提示。

0

我建議你使用try-catch-finally塊,

finally

親切關閉會話

try {   
     tx.commit(); 
    } catch (HibernateException e) { 
     handleException(e); 
    } finally { 
     hibernateSession.close(); 
    } 

而且,
postgresql.conf裏面的max_connections財產是100默認。如果你需要的話增加它。

+0

正如我在我的問題寫道,調用'hibernateSession.close()'導致線程「主題-18」 org.hibernate.SessionException'例外:會話關閉'! 'tx.commit()'已經關閉了會話。增加'max_connections'至200(和重新啓動)沒有什麼變化:(我也改變'<屬性名= 「connection.provider_class」> org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider'從廢棄的'org.hibernate作爲。 。connection.C3P0ConnectionProvider' – LancerX

1

我不太確定這裏發生了什麼事,但我建議你不要將hibernate.c3p0.acquireRetryAttempts設置爲1.首先,呈現下一個設置hibernate.c3p0.acquireRetryDelay不相關 - 設置重試嘗試之間的時間長度,但如果只有一次嘗試(確定,參數名稱具有誤導性,它會設置嘗試的總次數),則不會重試。您的設置的效果僅僅是讓客戶端在客戶端進入時嘗試獲取連接,然後在客戶端出現故障時立即向客戶端拋出異常。它完全不會限制池將嘗試獲取的連接數量(除非您將breakOnAcquireFailure設置爲true,在這種情況下,使用您的設置,任何未能獲取連接將導致整個池無效)。

我分享了sola對您缺乏可靠資源清理的擔憂。如果在你的設置下,commit()意味着close()(你不允許顯式地調用close(這看起來很糟糕)),那麼它應該是在finally塊中的提交(但是在finally塊中提交也看起來很糟糕,有時你不想提交)。無論關閉/提交問題,使用您擁有的代碼,偶爾在openSession和commit之間發生異常都會導致Connection泄漏。

但是,這不應該是你的太多開放連接問題的原因。如果泄漏Connections,您會發現連接池最終會凍結(因爲泄漏導致maxPoolSize Connectiosn將永久簽出)。你只有25個開放的連接。其他事情正在發生。嘗試查看您的日誌。多個連接池以某種方式被初始化? (c3p0在pool init的INFO級別上轉儲配置信息,因此如果打開多個池,應該會看到多條消息。或者,您可以通過JMX檢查運行的c3p0池,以查看是否爲什麼打開了超過25個連接。 )

祝你好運!

+0

你是對的C3P0初始化池41次,並顯示初始化C3P0池中的消息'... [email protected] [ConnectionPoolDataSource的 - > com.mchange.v2.c3p0.WrapperConnectionPoolDataSource @ a959e809 [acquireIncrement - > 1,acquireRetryAttempts - > 30,acquireRetryDelay - > 1000,autoCommitOnClose - >假,automaticTestTable - >空值,breakAfterAcquireFailure - >假,checkoutTimeout - > 0,connectionCustomizerClassName - >空值,connectionTesterClassName - > com.mchange。 v2.c3p0.impl ...'這個版本是縮短,因爲它是太長了。可能是什麼原因? – LancerX

+1

好,C3P0是不是做自主。我猜無論是設置中的某些內容導致許多c3p0數據源被實例化,還是您使用許多不同的用戶/密碼對來訪問該池。 (C3P0創建要求它的每一個用戶/密碼對一個獨立的游泳池。) –

+0

我預計這種答案:)我一定要找到原因。指向你,謝謝你! – LancerX