2

Hibernate 3 と postgres で開発した Web アプリで問題が発生しました。問題は、実行およびコミットされたすべての単一クエリがプール内の接続を解放しないことです (制限 = 100)。アクション(SELECT、INSERTなど)の後にDBにいくつかのクエリを実行し、結果を得ました:

クエリ:

SELECT pid, query, state FROM pg_stat_activity;
5436;"SELECT...";"idle" <- これで問題ありません
6776;"SELECT..." ;active" <- これで問題ありません
5324;"コミット";"アイドル"    
6840;"コミット";"アイドル"    
6276;"コミット";"アイドル"    
4804;"コミット";"アイドル"    
5812;"コミット";"アイドル"    
2608;"コミット";"アイドル"    
2576;"コミット";"アイドル"    
3896;"コミット";"アイドル"    
4660;"コミット";"アイドル"    
692;"コミット";"アイドル"

ご覧のとおり、問題はコミットされたトランザクションであり、それらは接続プールに留まり、ブロックされます。次のアクションにより、これがどんどん大きくなり、プールが過剰になるとDBに接続できなくなります。それらを手動で削除する方法 (SELECT pg_terminate_backend()) があることは知っていますが、Hibernate での解決策を好みます。私のコードに行きましょう、多分それは片付くでしょう。

これは、私の DBManager (クエリを実行して DB を管理するクラス) のメソッドの例です。

public List getGroups()
{
    Session session = sessionFactory.openSession();
    List<Group> groups = new ArrayList<Group>();

    try
    {
        session.beginTransaction();
        groups = session.createQuery( "from Group WHERE locked='FALSE' ORDER BY startHours" ).list();
        session.getTransaction().commit();

    }
    catch ( Exception e )
    {
        // logs
    }
    finally
    {
        try
        {
            session.close();
        }
        catch ( Exception e )
        {
        }
    }

    return groups;
}

他の方法はすべて同じ方法で行われます。私のセッションファクトリはクラスレベルで定義されています:

  public class DBManager
  {

   SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();

    public DBManager()
    {

    }

     // METHODS HERE
  }

何が間違っているのか教えてください... セッションは 経由で開かれ、閉じられtry{}catch{}finally{}ます。コミット後、トランザクションが適切に閉じられていないようです。

これが私のhibernate.cfgです:

    <!-- Database connection settings -->
    <property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
    <property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/szkola_plywania_test</property>
    <property name="hibernate.connection.username">postgres</property>
    <property name="hibernate.connection.password">postgres</property>

    <!-- JDBC connection pool(use the built-in) -->
    <property name="hibernate.connection.pool_size">1</property>

    <!-- SQL dialect -->
    <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>

    <property name="hibernate.connection.release_mode">after_statement</property>    

    <!-- Disable the second-level cache -->
    <property name="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

    <!-- Echo all executed SQL to stdout -->
    <property name="hibernate.show_sql">true</property> <!-- wynik pokazywany w konsoli -->

    <!-- Drop and re-create the database schema on startup -->
    <property name="hibernate.hbm2ddl.auto">update</property> <!-- create - nadpisywanie, update - dopisywanie -->

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

 <property name="hibernate.c3p0.acquire_increment">1</property>
    <property name="hibernate.c3p0.idle_test_period">100</property> <!-- seconds --> 
    <property name="hibernate.c3p0.max_size">100</property> 
    <property name="hibernate.c3p0.max_statements">0</property> 
    <property name="hibernate.c3p0.min_size">10</property> 
    <property name="hibernate.c3p0.timeout">100</property> <!-- seconds -->

    <!-- Names the annotated entity class -->
    <mapping class="com.school.hibernate.dto.User" />
    <mapping class="com.school.hibernate.dto.MailConfig" />
    <mapping class="com.school.hibernate.dto.Group" />
    <mapping class="com.school.hibernate.dto.Child" />
    <mapping class="com.school.hibernate.dto.Term" />
    <mapping class="com.school.hibernate.dto.Counter" />
    <mapping class="com.school.hibernate.dto.Invoice" />
    <mapping class="com.school.hibernate.dto.AgeGroup" />
    <mapping class="com.school.hibernate.dto.GroupTerm" />
    <mapping class="com.school.hibernate.dto.Instructor" />
    <mapping class="com.school.hibernate.dto.PassInstance" />
4

1 に答える 1

5

idle問題はありません。何もしないオープンな接続です。

idle in transactionこれらの接続は積極的にデータの「ロック」を保持しているため、問題になります (たとえば、自動バキュームが適切に機能しなくなる可能性があります)。

表示された pg_stat_activity の結果は、問題を示していません。

ご覧のとおり、問題はコミットされたトランザクションであり、それらは接続プールにとどまり、それをブロックします

いいえ、彼らは「ブロック」しません(少なくとも、その兆候は示していません)。プールは単にそれらを開いたままにします - これが接続プールの機能です。

DBMS への接続を開くのは非常にコストのかかる操作であるため、再利用できるように開いたままにしておくことをお勧めします。

(何らかの理由で) 開いている接続の数を減らしたい場合は、そうするように接続プールを構成する必要があります (たとえば、「アイドル」タイムアウトを下げることによって)。すべてが正常かどうかを判断するために、接続プールの構成を提示してください。

于 2013-02-28T12:41:36.467 に答える