使用Hibernate和mysql的连接太多

时间:2012-05-28 11:01:13

标签: mysql hibernate

我正在使用Hibernate 3和mysql sever 5.5 for myweb application with spring 3.0

由于太多连接,我得到例外......

我创建会话的java文件如下:

public class DBConnection {

    static{

    }

    public Session getSession(){

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

    }

}

我在需要会话

的地方调用此方法

as

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>

5 个答案:

答案 0 :(得分:23)

这是因为您正在使用在构建SessionFactory时立即创建的连接池,但只有在您打开Session时才会获取连接。现在,您正在关闭会话,因为会话已释放,但未关闭并由池保留。现在,您再次创建一个SessionFactory,从而创建一个新池,然后创建一个会话,从而创建一个新连接等等......最终将达到允许的最大连接数。

您需要做的是使用一个连接池(使用一个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();
     }
}

答案 1 :(得分:2)

每次需要SessionFactory并且不关闭它们时,您都会创建新的Session

通常,您只需在应用程序启动期间创建一次会话工厂,并在关闭期间关闭它。例如,如下:

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();
    }
}

另请查看contextual sessions pattern

答案 2 :(得分:0)

我用过

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

获取会话。在DAO层之上,带有注释的事务(@Transactional)用于添加,编辑或删除。我们的应用程序使用shiro进行身份验证和授权在每个页面访问中,它至少创建5个连接。因此后续请求继续增加mysql连接。感谢@Venu,我发现了

show variables like "max_connections";

显示可用的默认最大连接数。最初(我猜)它被设置为151.这个数字很快就会耗尽,因为另一个变量“innodb_open_files”设置为300.通过直觉,我可以说如果一个表达到300的最大连接,它只会用于清理(就像java中的垃圾收集。

有人会想,如果我们将“max_connections”的值增加到300就会解决这个错误,但正如我之前所说的那样,“innodb_open_files”在一个表达到该限制之前不会进行清理。在我们的例子中,经常调用的用户表将达到清除的限制。这意味着,您无法事先知道“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个连接。

答案 3 :(得分:0)

我在使用Hibernate mysql时遇到了同样的问题 以下两件事有助于解决我的连接问题

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>

答案 4 :(得分:-2)

  

JAVA ISSUE

     

请检查此答案:https://stackoverflow.com/a/10785770/598424

MYSQL ISSUE

您需要登录为超级用户。然后执行此代码:

SET GLOBAL MAX_CONNECTIONS = 200;

然而,这只是在MYSQL服务器重新启动之前发生的。如果您想要永久更改它,您可以在MYSQLD部分下添加以下内容。

MAX_CONNECTIONS = 500

OR

如果您在数据库服务器上有太多的过程,那么您可以达到限制,并且不允许任何新的操作开始。

要查看是否是这种情况,请通过键入以下内容从MySQL监视器提示中查看您的进程:

show processlist;

然后你会看到挥之不去的过程。每个都有一个ID,您可以通过键入以下命令在MySQL监视器中按进程ID终止它们:

 kill 2309344;