Как исправить «SQLServerException: соединение закрыто». появление в этом блоке Try-With-Resources?

Я делаю тестирование производительности СУБД. Я должен сделать это вручную для моей магистерской диссертации. У меня должно быть определенное количество потоков, каждый из которых открывает свое собственное соединение JDBC с базой данных (пул соединений невозможен) и совершает одинаковое количество одних и тех же транзакций (каждый поток выполняет одну и ту же работу). Мое соединение открыто как ресурс в блоке try-with-resources. Соединение должно оставаться открытым до конца области try-with-resources, но иногда это происходит, а иногда нет.

try (Connection conn = getConn();
    PreparedStatement simpleSelectStmt = conn
                         .prepareStatement(tcInstance.getQueryMap().get("SimpleSelect").getSimpleSelect())) {

        setConnIsolation(conn);

        long startTime = System.nanoTime();
        singleThread.execute(new Runnable() {

            @Override
            public void run() {

                for (int j = 0; j < tcInstance.getnT(); j++) {
                    try {
                        conn.setAutoCommit(false);
                        simpleSelectStmt.execute();
                        conn.commit();
                    } catch (Exception e) {
                        error++;
                        if (detectDeadlock(e.getMessage())) {
                            deadlock++;
                            System.out.println("Deadlock detected!");
                        } else {
                            e.printStackTrace();
                        }

                        try {
                            if (conn != null) {
                                conn.rollback();
                            }
                        } catch (SQLException e1) {
                            System.out.println("There was an error in rolling back the transaction.");
                            e1.printStackTrace();
                        }

                    }

                    if (j != (tcInstance.getnT() - 1)) {
                        try {
                            Thread.sleep(t);// ms
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }

                measureCPUusage(Thread.currentThread().getId());
                singleThread.shutdown();

        });

        long endTime = System.nanoTime();
        ....doing some other measurements....

    } catch (Exception e) {
        System.err.println("Error");
    }

Это метод getConn(), используемый для получения соединения jdbc:

private Connection getConn() throws SQLException {
    return DriverManager.getConnection(tcInstance.getJDBCurl(), tcInstance.getUser(), tcInstance.getPassword());
}

Я ожидал, что соединение будет открыто через весь блок try-with-resources, но есть исключения «Соединение закрыто» в строках conn.setAutoCommit(false); и conn.rollback();

Разве каждый поток не должен иметь свое собственное соединение?

XtremeBaumer 22.05.2019 11:06

Да, должны. У меня есть одно соединение на поток, и все транзакции этого потока (nT из них) используют это одно соединение. По крайней мере, я думаю, что у меня так. Я делаю это неправильно? Для фона: весь этот блок try-with-resources находится внутри метода work() класса, который представляет один поток, экземпляр этого класса создается на каждой итерации цикла в классе Main.

Lucija 22.05.2019 11:23

Вы должны переместить try-with-resource в метод singleThread.execute

XtremeBaumer 22.05.2019 11:25

Большое спасибо, я сделал, как вы предложили, и исключение больше не возникает. Я хотел бы проголосовать за ваш комментарий, но мне нужно 15 репутации, чтобы эта опция была включена (я здесь новичок)... Спасибо, спасибо, спасибо!

Lucija 22.05.2019 12:40
Основы программирования на Java
Основы программирования на Java
Java - это высокоуровневый объектно-ориентированный язык программирования, основанный на классах.
Концепции JavaScript, которые вы должны знать как JS программист!
Концепции JavaScript, которые вы должны знать как JS программист!
JavaScript (Js) - это язык программирования, объединяющий HTML и CSS с одной из основных технологий Всемирной паутины. Более 97% веб-сайтов используют...
0
4
84
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Пожалуйста, откройте отдельное соединение для каждого потока. Ваше открытое соединение для одного потока закрывается другим потоком, и, следовательно, вы получаете исключение. Кроме того, предоставьте дополнительную информацию об обнаруженииDeadlock, чтобы помочь вам в дальнейшем. Я надеюсь, что вам не нужны такие вещи для простых подключений в многопоточных средах.

Ответ принят как подходящий

Короче говоря, ваш поток кода выглядит примерно так:

try (Connection conn = getConn()) {
    setConnIsolation(conn);

    // Posted from Thread-1
    singleThread.execute(new Runnable() {

        @Override
        public void run() {

        // Thread-2 accesses conn created on Thread-1
        // use conn here..
    });

   // ....doing some other work....

} catch (Exception e) {
    System.err.println("Error");
}

//Conn is released

К тому времени, когда исполняемый объект начнет свою работу, соответствующий поток может использовать освобожденное соединение. Это связано с тем, что поток публикации после публикации исполняемого файла выходит из блока Try-With-Resources, и как его часть Conn освобождается.

Решение: Выведите Conn из блока Try-With-Resources.

Другие вопросы по теме