我集成的数据库配置为连接空闲(一段时间未使用),然后连接断开。由于我在持久配置中使用 spring batch,因此在运行的线程上始终有一个活动的数据库连接。
我的一个 spring 批处理作业依赖于来自外部 Web 服务的数据,这需要很长时间才能执行。这就是为什么当我得到结果时我已经失去了数据库连接。
我尝试在 web 请求发生之前使用 taskscheduler 注册心跳查询(从双重中选择 1),它每 5 分钟执行一次查询以保持连接有效,但即使查询定期执行,我猜它也是在一个单独的连接,因为它在另一个线程上运行。
有人有其他建议可以在锁定线程时保持连接活动吗?
我使用 JPA 的 EntityManager 进行 haertbeat 查询
如果你使用 Spring,那么你也可以使用 HikariCP。最近的 JDBC 标准定义了方法 isValid() 所以你不必调用 SQL 来检查 Connection 是否存在。
还有一种你可以使用的机制。它被称为 TCP 保活。 如果您将节
ENABLE=BROKEN
插入到您的 JDBC url 中,Oracle JDBC 驱动程序将在 TCP 连接上启用 TCP Keepalive 功能
jdbc:oracle:thin:@(DESCRIPTION=(ENABLE=BROKEN)(ADDRESS=(PROTOCOL=tcp)(PORT=1521)(HOST=myhost))(CONNECT_DATA=(SERVICE_NAME=orcl)))
然后即使您的线程被阻塞,Linux 内核也会通过 TCP 连接发送 keepalive 探测。
注意:第一次探测的延迟和频率由 Linux 内核参数决定。
# cat /proc/sys/net/ipv4/tcp_keepalive_time
7200
# cat /proc/sys/net/ipv4/tcp_keepalive_intvl
75
# cat /proc/sys/net/ipv4/tcp_keepalive_probes
9
默认情况下,第一个 keep alive 探测(TCP 窗口携带 0 字节)在 2 小时后发送。 而 Cisco/Juniper 通常会在一小时后切断 TCP 连接。所以通常你需要 root 权限来将 tcp_keepalive_time 的值降低到 15 分钟左右。