3

次のコードがあります

    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 - com.mchange.v2.resourcepool.BasicResourcePool$AcquireTask@ee4084 -- 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 closedtx.commit()

4

3 に答える 3

1

c3p0 がこのように動作する原因がわかりました。問題は非常に些細なことでした...コードのこの部分:

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

複数回実行されました。ヒントをくれたスティーブに感謝します。

于 2012-10-17T18:41:26.277 に答える
1

ここで何が起こっているのかよくわかりませんが、hibernate.c3p0.acquireRetryAttempts を 1 に設定しないことをお勧めします。再試行しますが、試行が 1 回しかない場合 (パラメーター名が誤解を招く可能性があります。試行の総数を設定します)、再試行はありません。設定の効果は、クライアントが来るたびにプールが接続を取得しようとし、それが失敗した場合はすぐに例外をクライアントにスローすることです。プールが取得しようとする接続の数はまったく制限されません (breakOnAcquireFailure を true に設定しない限り、設定により、接続の取得に失敗するとプール全体が無効になります)。

信頼できるリソースのクリーンアップの欠如についての sola の懸念を共有します。あなたの設定で commit() が close() を意味する場合 (そして、明示的に close を呼び出すことは許可されていませんか? それは悪いようです)、finally ブロックにあるのは commit です (ただし、finally ブロックでの commit も悪いようです)。 、コミットしたくない場合もあります)。クローズ/コミットの問題が何であれ、あなたが持っているコードでは、openSessionとコミットの間の時折の例外が接続リークにつながります。

しかし、それがオープン接続が多すぎる問題の原因であってはなりません。接続をリークすると、接続プールが最終的にフリーズすることがわかります (リークのために maxPoolSize Connectiosn が永久にチェックアウトされるため)。開いている接続は 25 しかありません。他にも何かが起こっています。ログを確認してみてください。複数の接続プールが何らかの方法で初期化されていますか? (c3p0 は、プールの初期化時に INFO レベルで構成情報をダンプするため、複数のプールが開かれている場合は、複数のメッセージが表示されるはずです。または、JMX を介して実行中の c3p0 プールを検査し、25 を超える接続が開かれたかどうか、またその理由を確認できます。 )

幸運を!

于 2012-10-16T18:06:31.323 に答える
0

try-catch-finally ブロックを使用することをお勧めします。

finally セッションを閉じてください

すなわち

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

また、 postgresql.conf
の プロパティはデフォルトで 100 です。 max_connections 必要に応じて増やしてください。

于 2012-10-16T12:01:39.883 に答える