【问题标题】:ExecutorService causes JDBC connection IssueExecutorService 导致 JDBC 连接问题
【发布时间】: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。请任何人告诉我问题出在哪里。

【问题讨论】:

    标签: java jdbc


    【解决方案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/…) 描述了一个类似的问题,并暗示问题可能出在代码本身,例如事务正在启动但从未完成。请注意,如果您按顺序运行事务,则可能不会出现此类问题,就像您的情况一样。
    猜你喜欢
    • 2010-10-03
    • 2023-03-27
    • 2012-12-24
    • 2011-04-01
    • 2018-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多