【问题标题】:How to avoid query execution timeout in PostgreSQL?如何避免 PostgreSQL 中的查询执行超时?
【发布时间】:2017-10-23 17:45:06
【问题描述】:

我正在对具有 10M 条记录的表运行以下更新查询,

update table1 t1 set col1=(select coalesce((select t2.col2 from table1 t2 where t1.col3=t2.col4 limit 1), null));

当我在查询上方运行时,我收到以下异常,因为执行查询需要很长时间,

java.net.SocketException: Socket closed
    at java.net.SocketInputStream.socketRead0(Native Method) ~[na:1.8.0_121]
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) ~[na:1.8.0_121]
    at java.net.SocketInputStream.read(SocketInputStream.java:171) ~[na:1.8.0_121]
    at java.net.SocketInputStream.read(SocketInputStream.java:141) ~[na:1.8.0_121]
    at sun.security.ssl.InputRecord.readFully(InputRecord.java:465) ~[na:1.8.0_121]
    at sun.security.ssl.InputRecord.read(InputRecord.java:503) ~[na:1.8.0_121]
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973) ~[na:1.8.0_121]
    at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:930) ~[na:1.8.0_121]
    at sun.security.ssl.AppInputStream.read(AppInputStream.java:105) ~[na:1.8.0_121]
    at org.postgresql.core.VisibleBufferedInputStream.readMore(VisibleBufferedInputStream.java:146) ~[postgresql-9.4.1207.jre7.jar:9.4.1207.jre7]
    at org.postgresql.core.VisibleBufferedInputStream.ensureBytes(VisibleBufferedInputStream.java:115) ~[postgresql-9.4.1207.jre7.jar:9.4.1207.jre7]
    at org.postgresql.core.VisibleBufferedInputStream.read(VisibleBufferedInputStream.java:71) ~[postgresql-9.4.1207.jre7.jar:9.4.1207.jre7]
    at org.postgresql.core.PGStream.ReceiveChar(PGStream.java:283) ~[postgresql-9.4.1207.jre7.jar:9.4.1207.jre7]
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1719) ~[postgresql-9.4.1207.jre7.jar:9.4.1207.jre7]
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:173) ~[postgresql-9.4.1207.jre7.jar:9.4.1207.jre7]
    ... 64 common frames omitted
Wrapped by: org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:201) ~[postgresql-9.4.1207.jre7.jar:9.4.1207.jre7]
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:622) ~[postgresql-9.4.1207.jre7.jar:9.4.1207.jre7]
    at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:458) ~[postgresql-9.4.1207.jre7.jar:9.4.1207.jre7]
    at org.postgresql.jdbc.PgStatement.executeUpdate(PgStatement.java:406) ~[postgresql-9.4.1207.jre7.jar:9.4.1207.jre7]
    at org.springframework.jdbc.core.JdbcTemplate$1UpdateStatementCallback.doInStatement(JdbcTemplate.java:523) ~[spring-jdbc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate$1UpdateStatementCallback.doInStatement(JdbcTemplate.java:520) ~[spring-jdbc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:404) ~[spring-jdbc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    ... 58 common frames omitted

有没有一种方法可以让我简单地说,“只需触发查询,不要等待响应”,这样我就可以避免套接字超时?我正在使用 spring 提供的 JDBC 模板。

【问题讨论】:

  • 合并似乎是多余的。

标签: postgresql spring-jdbc


【解决方案1】:

我可以给你两个实用的解决方案:

  1. new Thread(){...}.start() 中执行查询。更好的是创建轻量级Runnables 并将它们提供给Executors.newCachedThreadPool()

  2. 使用类型安全的查询构造器语言,例如 JOOQ 或 QueryDSL。 JOOQ 可以从数据库生成类型安全的类,供您创建查询。这些类具有您需要的所有异步实现:dsl.update(TABLE1).set(...).executeAsync()

但是,仍然存在一个主要问题:您想避免套接字超时还是忽略它?

以上是忽略套接字超时。 通过避免套接字超时,以下解决方案可能更适合:

  1. 捕捉错误并做出反应。例如:告诉用户,要更新的记录太多了。
  2. update 语句拆分为多个批次(在后台),因此更新将始终成功。 (有一些工具可以轻松地为您做到这一点。JOOQ 也可以为您做到这一点)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-17
    • 2021-11-15
    相关资源
    最近更新 更多