【问题标题】:PostgreSQL Exception: "An I/O error occured while sending to the backend"PostgreSQL 异常:“发送到后端时发生 I/O 错误”
【发布时间】:2023-04-01 11:07:01
【问题描述】:

我正在测试一些处理网站注册的代码。 java代码如下(摘录):

if (request.getParameter("method").equals("checkEmail")){
            String email= request.getParameter("email");
            ResultSet rs =null;
            PreparedStatement ps = db.prepareStatement(query);
            ps.setString(1, email);
            rs = ps.executeQuery();             
            if(rs.next()){ 
                            //email already present in Db 
            } else {
                            //proceed with registration.....

在大多数情况下,进程执行没有任何问题,但我遇到了一个间歇性问题,因为与数据库的连接正在关闭,所以它失败了。每次失败时,它都会在同一点失败 - 运行上面的准备好的语句时(显然会检查正在提交的电子邮件是否已经在数据库中)。

Postgres 的版本是 8.1.23

任何帮助或建议表示赞赏。 Stacktrace 如下(编辑:有时 Stacktrace 说由 Stream Closed 引起,有时 Socket Closed 如下所示):

13:53:00,973 ERROR Registration:334 - org.postgresql.util.PSQLException: An I/O error occured while sending to the backend.

  at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:283)
  at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:479
  at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:367)
  at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:271)
  at Registration.doPost(Registration.java:113)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
  at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
  at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
  at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
  at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
  at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
  at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
  at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:567)
  at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
  at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
  at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:190)
  at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:291)
  at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:769)
  at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:698)
  at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:891)
  at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:690)
  at java.lang.Thread.run(Thread.java:595)

Caused by: java.net.SocketException: Socket closed

  at java.net.SocketInputStream.socketRead0(Native Method)
  at java.net.SocketInputStream.read(SocketInputStream.java:129)
  at org.postgresql.core.VisibleBufferedInputStream.readMore(VisibleBufferedInputStream.java:135)
  at org.postgresql.core.VisibleBufferedInputStream.ensureBytes(VisibleBufferedInputStream.java:104)
  at org.postgresql.core.VisibleBufferedInputStream.read(VisibleBufferedInputStream.java:73)
  at org.postgresql.core.PGStream.ReceiveChar(PGStream.java:259)
  at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1620)
  at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
    ... 22 more      

【问题讨论】:

  • 您是否正在创建单个数据库连接并长时间保持打开状态?
  • 套接字正在被服务器关闭,可能是由于空闲超时。

标签: java postgresql io


【解决方案1】:

虽然现在回答很晚,但我希望这可能会对某人有所帮助。

我遇到了同样的异常,但我连接到同一主机上的本地数据库。
原因是连接失效了,需要重新打开。

postgresql.org 上有一个ticket,它有一个相关的主题。他们的答案非常相似,只是捕获异常并重新打开连接

PostgreSQL 版本:8.4

【讨论】:

  • 本地主机上的 9.3.2 上相同(来自通过命令行调用的 java jar)
  • 我也遇到了同样的问题。但我想知道连接如何变得无效?
  • 我认为是因为在特定时间跨度内未使用连接时套接字超时。
  • 我得到了同样的结果。它是一个 springboot 项目,我使用 Hikari 连接池。Hikari 管理所有与连接相关的东西。在这种情况下我该如何解决这个问题?
  • @ShamilPuthukkot 您在使用最新的 Spring Boot 和 Hikari 版本吗?您是否调整了任何 Hikari 配置参数?也请看看这个tutorial。亲切的问候,大卫
【解决方案2】:

我怀疑您的应用程序和数据库位于不同的机器上,并且在两者之间有一个(有状态的)防火墙。我的猜测是防火墙在打开一定时间后断开连接,可能没有流量。在将断开的连接交给您之前,连接池将无法检测到这一点。

唯一让我怀疑的是它总是发生在代码中的同一个地方,但如果这是新会话中的第一个数据库查询(或类似的东西),它总是出现在同一个地方。

【讨论】:

  • 感谢您的回答。 @Dave - 我已经尝试了两种方法,在查询之前打开一个新连接,并从以前的查询中打开它。无论哪种方式,问题都会重现。
  • 但是“新”连接是来自连接池还是真的是新连接?如果它来自池,则连接可能在您获得它时已断开。
  • 我目前没有使用 Wobbly 的连接池。
【解决方案3】:

我在测试中遇到了同样的问题,但原因是在创建 PreparedStatement 和调用 executeUpdate 方法之间调用了 nextSequenceId,使用相同的 Connection 对象。 我的解决方案是将 nextSequenceId 的调用移到方法的顶部,问题就消失了。

【讨论】:

    【解决方案4】:

    我有同样的问题并解决了我的变化是其中任何一个:

    • 您的查询非常大,例如:

      SELECT * FROM 'Table' WHERE id in ?param

    param 是一个大列表。

    • 您的结果非常大(例如超过 4 GIG)

    【讨论】:

    • @danilo 我的结果非常大,我正在对结果进行分页。
    【解决方案5】:

    我遇到了同样的异常。

    在我的情况下,由于某些查询大量使用内存,我的数据库正在重新启动。这就是我在重新启动数据库期间收到该错误的原因。

    解决方案:我优化了我的查询。

    【讨论】:

      【解决方案6】:

      这主要适用于开发环境。

      如果有人最近遇到这个问题,并且同时在 Ubuntu 19.10 下使用 docker v19.03.5,它往往会中断某些网络管理器配置的网络连接。我没有机会详细调试此问题,但如果您遇到此问题,我强烈建议您尝试

      $ sudo service docker stop
      

      再给连接一个机会。

      像魅力一样为我工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-07-22
        • 2015-12-07
        • 2011-04-28
        • 2017-08-31
        • 1970-01-01
        • 2013-01-30
        • 1970-01-01
        相关资源
        最近更新 更多