6

Spring3.0のmywebアプリケーションにHibernate3とmysqlsever5.5を使用しています

接続が多すぎるため、例外が発生します......

セッションを作成するJavaファイルは次のとおりです。

public class DBConnection {

    static{

    }

    public Session getSession(){

         Session session = null;
         SessionFactory sessionFactory= null;
         sessionFactory = new Configuration().configure().buildSessionFactory();
        session = sessionFactory.openSession();
        return session;

    }

}

セッションが必要な場所でこのメソッドを呼び出します

なので

Session session=new DBConnection().getSession();

以降

transaction.commit();

を使用してセッションを閉じます

session.close();

問題解決を手伝ってください……

私のhibernate.cfg.xmlは:

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
  <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
  <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/dbname</property>
<property name="hibernate.connection.username">root</property>

  <property name="hibernate.connection.password">lax</property>
  <property name="hibernate.connection.pool_size">100</property>
  <property name="show_sql">true</property>
  <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
  <property name="hibernate.hbm2ddl.auto">update</property>
  <property name=""></property>

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

</session-factory>
</hibernate-configuration>
4

5 に答える 5

26

これは、SessionFactoryをビルドするとすぐに作成された接続プールを使用しているためですが、接続はセッションを開いたときにのみ取得されます。これで、接続が解放されたためにセッションを閉じていますが、閉じられておらず、プールによって保持されています。ここで、再びSessionFactoryを作成し、新しいプールを作成し、次にセッションを取得して、新しい接続を作成します。これにより、最終的に許可される接続の最大数に達します。

あなたがしなければならないのは、1つの接続プールを使用して(1つのSessionFactoryを使用して)、同じプールから接続を取得および解放することです。

public class DBConnection {

      private static SessionFactory factory;
      static {
            factory = new Configuration().configure().buildSessionFactory();
      }

      public Session getSession() {
            return factory.openSession();
      }

      public void doWork() {
           Session session = getSession();
           // do work.
           session.close();
      }

     // Call this during shutdown
     public static void close() {
          factory.close();
     }
}
于 2012-05-28T13:52:00.853 に答える
5

SessionFactoryが必要になるたびに新しいを作成Sessionし、閉じないでください。

通常、セッションファクトリは、アプリケーションの起動時に1回だけ作成し、シャットダウン時に閉じる必要があります。たとえば、次のようになります。

public class DBConnection {
    private static SessionFactory factory;
    static {
        factory = new Configuration().configure().buildSessionFactory();
    }

    public Session getSession() {
        return factory.openSession();
    }

    // Call this during shutdown
    public static void close() {
        factory.close();
    }
}

また、コンテキストセッションパターンも見てください。

于 2012-05-28T11:17:37.640 に答える
1

利用した

Session session = SessionFactoryUtils.getSession(this.sessionFactory,
                true);

セッションを取得します。DAOレイヤーの上では、注釈付きのトランザクション(@Transactional)が追加、編集、または削除に使用されます。このアプリケーションでは、認証と承認にshiroを使用しています。各ページアクセスで、少なくとも5つの接続が作成されます。したがって、後続のリクエストはmysql接続を増やし続けます。@Venuのおかげで私はそれを見つけました

show variables like "max_connections";

使用可能なデフォルトの最大接続を示します。最初は(おそらく)151に設定されていました。別の変数「innodb_open_files」が300に設定されていたため、この数はすぐになくなります。直感的には、1つのテーブルが最大接続数300に達した場合、クリーンアップのみが行われます。 Javaでのガベージコレクション)。

「max_connections」の値を300に増やすと、このエラーは解決すると思いますが、前述したように、「innodb_open_files」は、1つのテーブルがその制限に達するまでクリーンアップされません。私たちの場合、頻繁に呼び出されるユーザーテーブルは、クリーンアップが行われるためのその制限に達します。つまり、「max_connections」の完全数を事前に知ることはできません。

mysql構成ファイル「/etc/mysql/my.cnf」でmax_connectionsは次のように設定されます

max_connections        = 1000

変わらなかった

「innodb_open_files」の値。デフォルトは「300」です。

mysql> show variables like "innodb_open_files";

プログラムの実行中に使用できます

mysql> show processlist;

開いている接続の数を確認します。スリープ状態のすべてのプロセスは、クリーンアップの次のサイクルで削除できると思います(ただし、これは私の推測です)。

1000人を超えるユーザーをシミュレートし、WebプロジェクトでURLを実行するには、jmeterなどのソフトウェアを使用して、スレッド(ユーザー)の数を1000に設定します。より多くのユーザーを使用するかどうかは、コンピューターで使用可能なRAMによって異なります。1秒間隔でリクエストを送信する3000を超える接続をシミュレートすることができました。これを行う方法に関する十分なチュートリアルがroseindiaにリストされています

今私のクエリ。私はどこでもセッションを閉じていません。@Transactionはその目的で作成されたと思います(制限に達するとすべての接続がクリーンアップされるため、mysqlはそれを証明します)。デタッチされたオブジェクトのマージの問題のため、OpenSessionInViewFilterを使用する必要がありました。OpenSessionInViewFilter(OpenSessionInViewInterceptorの場合もあります)は、マージが発生するまでセッションを少し長く開きます。これが、mysqlで非常に多くの接続が開いたままになる理由である可能性があります(明確にはわかりません)。それは非常に多くのユーザーのために機能するので、それは良い解決策のようですが、mysqlのデフォルトの最大接続サイズの下でそれを機能させるためのより良い解決策があります。つまり、151の接続。

于 2012-09-05T11:06:35.783 に答える
1

Hibernatemysql接続で同じ問題に直面していました次の2つのことが接続の問題の修正に役立ちました

import javax.inject.Singleton;

@Singleton
public class DBConnection {
private static SessionFactory factory;
static public Session getSession() {
    if (factory == null) {
        System.out.println("--------New connection----");

        factory = new Configuration().configure("hibernate.cfg.xml")
                .addAnnotatedClass(SomeClass.class)
                .buildSessionFactory();
    }
    //System.out.println("--------old connection----");

    return factory.openSession();
}


    // Call this during shutdown
    public static void close() {
        factory.close();
    }
}

DBConnectionを取得するためのシングルトンクラスを作成します

クエリが完了したら、session.close()を実行することを忘れないでください

また、「hibernate.cfg.xml」にこの行を追加します

<hibernate-configuration> <session-factory> .... <property name="connection.pool_size">100</property> .... </session-factory> </hibernate-configuration>

于 2020-05-30T15:05:31.910 に答える
-2

JAVAの問題

この回答を確認してください:https ://stackoverflow.com/a/10785770/598424

MYSQLの問題

スーパーユーザーとしてログインする必要があります。次に、このコードを実行します。

SET GLOBAL MAX_CONNECTIONS = 200;

ただし、これはMYSQLサーバーが再起動するまでしか持続しません。恒久的に変更したい場合は、MYSQLDセクションの下に次のように追加できます。

MAX_CONNECTIONS = 500

また

データベースサーバー上でプロセスが多すぎる場合は、制限に達する可能性があり、新しいプロセスを開始することはできません。

これが当てはまるかどうかを確認するには、次のように入力して、MySQLモニタープロンプトからプロセスを確認します。

show processlist;

次に、長引くプロセスが表示されます。それぞれにIDがあり、次のように入力することで、MySQLモニターでプロセスIDによってそれらを強制終了できます。

 kill 2309344;
于 2012-05-28T11:06:01.303 に答える