如何保持 jdbc 到 postgres 活着

Posted

技术标签:

【中文标题】如何保持 jdbc 到 postgres 活着【英文标题】:How to keep jdbc to postgres alive 【发布时间】:2014-10-01 13:26:34 【问题描述】:

所以我已经跟踪了一两天的错误,它发生在我几乎无法控制的远程服务器上。我的代码的来龙去脉是,我向我们的 UI 团队提供了一个 jar 文件,它包装了 postgres 并为用户导入的数据提供存储。由于多种原因,导入过程非常缓慢,其中之一是用户正在导入不可预测的大量数据(我们无法真正减少)。这导致了大量的超时问题。

经过一些初步调查,我已将其范围缩小到 jdbc 到 postgres 数据库超时。我在本地测试设置中复制它时遇到了很多麻烦,但最终通过将连接属性的 'socketTimeout' 减少到 10 秒(在连接上进行的每次调用之间的间隔超过 10 秒)终于设法做到了。

我现在的问题是,保持这种状态的最佳方法是什么?我已经将'tcpKeepAlive'设置为true,但这似乎没有效果,我需要手动轮询连接还是什么?根据我的阅读,我假设轮询是自动的,并且由操作系统控制。如果这是真的,我真的无法控制运行环境中的操作系统设置,处理这个问题的最佳方法是什么?

我正在考虑每次使用连接时都对其进行测试,如果超时,我将创建一个新连接。这是正确的做法还是有更好的方法来保持连接?我刚刚看过这篇文章,人们建议您应该为每个查询打开和关闭一个连接: When my app loses connection, how should I recover it?

在我的情况下,我有一系列顺序插入发生在单个线程上,如果单个线程失败,它们都会失败。为了实现这一点,我使用了事务:

m_Connection.setAutoCommit(false); 
m_TransactionSave = m_Connection.setSavepoint();

// Do something

m_Connection.commit(); 
m_TransactionSave = null; 
m_Connection.setAutoCommit(true);

如果我确实继续重新连接,或使用 PGBouncer 之类的连接池(如 cmets 中建议的那样),我如何在它们之间持久保存此事务?

【问题讨论】:

【参考方案1】:

到 PostGres 的 JDBC 连接可以使用 keep-alive 设置进行配置。此处针对此功能提出了一个问题:JDBC keep alive issue。此外,还有parameter help page。

根据上面的注释,您可以将以下内容添加到 JDBC 连接的连接参数中:

tcpKeepAlive=true;

减少 socketTimeout 应该会使事情变得更糟,而不是更好。 socketTimeout 衡量连接在预期数据到达时应该等待多长时间,但实际上并没有。我的直觉是让它更长,而不是更短。

您是否有可能使用PGBouncer?如果没有活动,该进程将主动终止来自服务器端的连接。

最后,如果您在 Linux 上运行,您可以使用以下命令更改 TCP 保持活动设置:keep alive settings。我确信 Windows 也存在类似的东西。

【讨论】:

感谢您的回复。我会调查的。如前所述,我使用了 tcpKeepAlive=true;这似乎没有做任何事情(我假设是因为我没有更改基于 Windows 的本地计算机上的操作系统设置)。至于超时,如前所述,我故意在我的本地机器上让它变得更糟,以验证它是一个超时问题。在实时服务器上,超时将是合理的。我目前没有使用 PGBouncer,我不熟悉使用连接池,但我担心它会如何与我的事务交互。

以上是关于如何保持 jdbc 到 postgres 活着的主要内容,如果未能解决你的问题,请参考以下文章

使用复制 Postgres jdbc 的正确方法

如何在悬停时保持 Bootstrap 弹出框活着?

保持子进程活着并继续给它命令? Python

升级 JDBC 驱动程序后,Postgres 中到整数的隐式类型转换失败

Postgres 11 问题:服务器上的“SSL 错误:DATA_LENGTH_TOO_LONG”错误

Spring Boot jdbc模板在自定义模式下的postgres中找不到表