ExecutorService 导致 JDBC 连接问题

Posted

技术标签:

【中文标题】ExecutorService 导致 JDBC 连接问题【英文标题】:ExecutorService causes JDBC connection Issue 【发布时间】:2015-09-17 14:51:11 【问题描述】:

许多 JDBC 调用(查询 DB 和获取结果)都是通过 ExecutorService 执行的。我发现当执行这些调用时,JDBC 连接需要很长时间才能关闭连接,即使这些连接已正确关闭。为什么我这么说是,当通过JMeter运行负载测试时,数据库显示很多连接在IDLE in transaction。如果运行测试的线程数很高,则事务中空闲的连接数会增加。如果测试运行缓慢,则连接会慢慢关闭(1、2 分钟),这意味着事务中有 IDLE 连接,但几分钟后它们变为 IDLE。我也在这里使用连接池。如果我将 JDBC 查询函数作为一个序列(一个接一个)运行,那么数据库不会在事务中的 IDLE 中显示任何连接。下面是我如何运行运行 JDBC 查询的可运行任务。 TaskManager 类处理整个 ExecutorService 相关的功能。

public class TaskManager 
    final private ThreadServiceFactory threadFactory;

    private int concurrentThreadCount;
    private  ExecutorService executerSV;
    private final CountDownLatch latch;

    // I keep a count of proposed tas task as servicecount
    public TaskManager(int serviceCount) 

        threadFactory = new ThreadServiceFactory();
        this.concurrentThreadCount = serviceCount;
        latch = new CountDownLatch(serviceCount);
    

    public void execute( ThreadService runnableTask) 
        Object rv = null;

        runnableTask.setCountDownLatch(latch);

        if(executerSV == null) 
            executerSV = Executors.newFixedThreadPool(this.concurrentThreadCount, getThreadFactory());
        

        executerSV.execute(runnableTask);
    

    public boolean holdUntilComplete()

        try 

            latch.await();
             executerSV.shutdown();
            return true;
         catch (InterruptedException e) 
            e.printStackTrace();
            return false;           
        

    

    private ThreadServiceFactory getThreadFactory()
            threadFactory.setDeamon( Boolean.FALSE);
        return threadFactory;

    


在我的测试课上;

 public void test()
            TaskManager tm = new TaskManager(3);

            tm.execute(queryTask1);
            tm.execute(queryTask2);
            tm.holdUntilComplete();

  

queryTask1 是一个 Runnable,它调用 JDBC 选择查询。

如果我运行queryTask1.run(); queryTask2.run();,那么数据库中的连接中没有任何空闲。

我使用java 7。请任何人告诉我问题出在哪里。

【问题讨论】:

【参考方案1】:

您的问题中没有任何代码可以打开与数据库的任何连接。因此,很难提出答案。但是,由于您声明您正在使用连接池,因此您应该更好地查看池配置参数,因为它们决定了空闲连接在被驱逐之前可以打开多长时间。例如,如果您在 tomcat 中运行连接池,则应特别查看“minIdle”、“maxIdle”和“minEvictableIdleTimeMillis”属性。见https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html

【讨论】:

感谢您的回答。当我一个接一个地运行 JDBC 调用(没有 ExecutorService)时,DB 中没有这样的“IDLE in transaction”连接。这是否意味着 JDBC 调用或池配置没有问题?我以多种方式尝试了我的代码,最后一项更改是更改了这些使用 Executor 运行的任务的方式,而没有,我发现,在作为序列运行时,事务中的 IDLE 不会出现。 不客气。如果没有您正在做的事情的更多详细信息(您正在运行的查询,您正在使用的 DBMS),我认为我不会有太大的帮助,但看起来您的查询存在并发问题。这篇文章 (serverfault.com/questions/660642/…) 描述了一个类似的问题,并暗示问题可能出在代码本身,例如事务正在启动但从未完成。请注意,如果您按顺序运行事务,则可能不会出现此类问题,就像您的情况一样。

以上是关于ExecutorService 导致 JDBC 连接问题的主要内容,如果未能解决你的问题,请参考以下文章

Android线程管理之ExecutorService线程池

ExecutorService接口概要

Oracle JDBC 驱动程序未在旧版 Web 应用程序中使用 JNDI 连接到数据库

ExecutorService对象的shutdown 和shutdownNow 的区别

使用ExecutorService实现线程池

JDK 源码解析 —— Executors ExecutorService ThreadPoolExecutor 线程池