【问题标题】:Spring @Transactional timeout does not work as expected with DB2Spring @Transactional 超时在 DB2 中无法按预期工作
【发布时间】:2020-06-26 20:49:43
【问题描述】:

我们有一个与 DB2 (LUW) 数据库集成的 spring 应用程序。

在一个特定的流程中,我们有一个用@Transactional(timeout=60)注释的方法

在数据库重负载时,我们观察到上述 60 秒的超时未能引发 准时例外。它仅在数据库处理成功完成或 有错误。

失败的消息如下所示:

2020-02-21 18:45:32,463 错误 ... 交易超时:截止日期为 2020 年 2 月 21 日星期五 18:40:14 EET 2020

请注意,在数据库释放资源后抛出异常,在特定情况下出现锁定超时错误,由于配置的事务超时,比我预期的晚了大约 5 分钟。

我试图通过手动导致数据库延迟来重现此行为。具体来说,我打电话给 我的应用程序中的睡眠 DB2 过程,时间长于配置的事务超时。我的测试结果是一样的,只有在sleep操作成功结束后才抛出异常。

我想用另一个数据库检查类似的场景,所以我创建了一个简单的 Spring boot 项目,其中包含 2 个不同的配置文件,一个用于 DB2,一个用于 Postgres。 运行这个示例,我观察到 DB2 的类似行为,即事务超时不会导致任何错误,或者它仅在为 DB2 配置的休眠时间(30 秒)(大于配置的事务超时(10 秒))结束后才会发生。

相反,Postgres 的行为或多或少是我所期望的。与数据库的连接在事务超时时间过去(10 秒)的确切时刻以异常结束,而无需等待睡眠操作完成(30 秒)。

示例项目是here。此处描述的示例如下:

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. 我尝试重现问题并测试多个 DB 的方式是否有意义,还是我遗漏了什么?
  2. 这更重要,:有没有办法让 DB2 连接在事务超时达到其限制的确切时刻失败?

【问题讨论】:

  • 您的 Db2 jdbc 驱动程序版本和类型是什么?从 ibm.com/support/pages/db2-jdbc-driver-versions-and-downloads 获取最新信息 在寻求 Db2 方面的帮助时,请始终指定您的 Db2 服务器平台(z/os、i 系列 os/400 或 linux/unix/windows)。
  • @mao 你说得对,我错过了这个。它是 DB2 LUW,驱动程序是 com.ibm.db2.jcc:db2jcc4:4.26.14,我相信它是最新的。你认为事务超时应该像我期望的那样工作吗?
  • 我不知道 Spring 在幕后做了什么,但如果普通 jdbc 的行为不像文档所述的那样,那么我会向 IBM 开一张票。不过,这些文档通常没有什么帮助。

标签: spring db2 spring-transactions db2-luw


【解决方案1】:

由于我发布问题已经有一段时间了,但没有人发布答案,我将把我的发现从问题的编辑部分移到这里:

解决方案似乎是设置 DB2 配置属性 queryTimeoutInterruptProcessingMode=2(而不是我最初认为的 interruptProcessingMode)

示例:jdbc:db2://localhost:50000/demo:queryTimeoutInterruptProcessingMode=2;

通过此修改,事务超时结束时会引发异常。不过还是想听听专家的意见。例如,修改特定属性是否安全?有什么影响?

【讨论】:

    猜你喜欢
    • 2022-10-21
    • 2017-09-06
    • 2017-04-23
    • 1970-01-01
    • 2015-05-19
    • 2020-03-20
    • 2020-05-12
    • 1970-01-01
    • 2013-06-17
    相关资源
    最近更新 更多