SessionFactory不停地createSession导致mysql进程超限制

2019-06-06 46 Lei 0

之前碰到过一个数据库(MySQL)相关的问题,表现是:

执行一个数据库相关的定时任务,执行一段时间后,数据库操作就一直等待,无法执行。用 SHOW PROCESSLIST; 看了一下MySQL的后台进程,发现达到了最大限制。我在jdbc.properties中配置了线程池中最大的进程数是jdbc.c3p0.maxPoolSize=200。所以当进程达到200个左右的时候,就分配不了新的进程,而旧的进程还没有释放,导致最新的数据库操作一直无法进行,处于等待中。


导致问题的原因是:

我会用SessionFactory的getCurrentSession()方法去获取当前的会话,如果没有拿到,那么就用createSession()方法创建新的。代码如下:

@Override
public  Session getSession() {
   try {
      // 尝试事务中获取会话
      session = this.sessionFactory.getCurrentSession();
      return session;
   } catch (Exception e) {
      session = this.sessionFactory.openSession();
      return session;
   }
}

当时我的代码在执行事务的时候出现了异常,导致一直在新建会话。当抛出异常(没有获取到当前的会话)的时候,就新建一个。新建的会话是不能使用之前的会话创建的数据库进程池中的进程的,所以导致旧的进程没法给到新的会话,而旧进程不能及时关闭,造成阻塞。导致这个问题的关键是异常中没有输出日志,也没有抛出,所以看不出问题在哪里,以至于我找了很久都找不到。


经验:

从这个问题中我得出两个经验:

1.如果数据库进程不能及时回收,造成进程阻塞,看一下有没有不停地创建数据库会话。

网上查了很多帖子,都是说数据库进程数设置的太小或者回收时间设置的太长(默认是8小时回收1次。)

2.异常一定要抛出到错误日志,或者打印到日志中去。


  0