Тайм-аут Spring @Transactional не работает должным образом с DB2 - PullRequest
0 голосов
/ 15 марта 2020

У нас есть приложение Spring, которое интегрируется с базой данных DB2 (LUW).

В указанном потоке c у нас есть метод, аннотированный @Transactional(timeout=60)

При большой нагрузке на базу данных мы заметили, что вышеупомянутый тайм-аут 60 секунд не может вызвать исключение по времени. Он делает это только тогда, когда обработка базы данных завершается либо успешно, либо с ошибкой.

Сообщения о сбоях подобны приведенным ниже:

2020-02-21 18: 45: 32,463 ОШИБКА ... Тайм-аут транзакции: крайний срок: пт 21 февраля 18:40:14 EET 2020

Обратите внимание, что исключение было выдано после освобождения ресурсов базами данных, с ошибкой тайм-аута блокировки в конкретный случай c, примерно на 5 минут позже, чем я ожидал из-за настроенного тайм-аута транзакции.

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

Я хотел проверить похожий сценарий с другой базой данных, поэтому я создал простой загрузочный проект Spring с 2 различными профилями, один для DB2 и один для Postgres. Выполняя этот пример, я наблюдаю аналогичное поведение для DB2, то есть время ожидания транзакции не вызывает никаких ошибок или оно происходит только после того, как время ожидания, сконфигурированное для DB2 (30 с), которое больше настроенного времени ожидания транзакции (10 с), заканчивается.

Напротив Postgres поведение более или менее то, что я ожидал бы. Соединение с БД завершается с исключением того момента, когда истекло время ожидания транзакции (10 с), не дожидаясь, пока операция сна завершится sh (30 с).

Пример проекта: здесь . Ниже приведен пример того, что описано здесь:

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class DemoService {

    @Autowired
    private DemoRepository repository;

    @Transactional(timeout = 10)
    public void sleep() {
        repository.sleep();
    }
}
package com.example.demo;

public interface DemoRepository {
    void sleep();
}

package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
@Profile("db2")
public class Db2DemoRepository implements DemoRepository {

    @Autowired
    private JdbcTemplate template;

    @Override
    public void sleep() {
        template.execute("call SYSIBMADM.DBMS_ALERT.SLEEP(30)");
    }
}
package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
@Profile("postgres")
public class PostgresDemoRepository implements DemoRepository {

    @Autowired
    private JdbcTemplate template;

    @Override
    public void sleep() {
        template.execute("select pg_sleep(30);");
    }
}

Я полагаю, что тайм-аут транзакции устанавливает тайм-аут запроса в Postgres и не может это сделать в DB2. Также я безуспешно пытался использовать несколько значений для следующих свойств конфигурации DB2: timerLevelForQueryTimeOut, interruptProcessingMode, queryTimeout.

Итак, на мои вопросы:

  1. Имеет ли способ, которым я пытаюсь воспроизвести проблему и протестировать несколько БД, имеет смысл или я что-то упустил?
  2. Это более важно ,: есть ли способ заставить соединение DB2 прервать именно в тот момент, когда истекает время транзакции достигает своего предела?

1 Ответ

0 голосов
/ 29 апреля 2020

Поскольку прошло много времени с тех пор, как я опубликовал вопрос, и никто не опубликовал ответ, я перенесу свои выводы из отредактированного раздела моего вопроса, здесь:

Решение, похоже, заключается в установке свойства конфигурации DB2 queryTimeoutInterruptProcessingMode=2 (а не interruptProcessingMode, как я изначально думал)

пример: jdbc:db2://localhost:50000/demo:queryTimeoutInterruptProcessingMode=2;

В этой модификации выдается исключение по истечении времени ожидания транзакции. Хотелось бы услышать мнение экспертов. Например, безопасно ли изменять указанное свойство c? Какое влияние?

...