我有一个 Spring 应用程序,它定期在 PostgreSQL-DB 中插入记录。现在,完成一组预定的导入后,需要几秒钟的时间才能收到以下警告:
com.zaxxer.hikari.pool.ProxyConnection : HikariPool-1 - Connection org.postgresql.jdbc.PgConnection@7d18a7dc marked as broken because of SQLSTATE(08006), ErrorCode(0)
接下来是这个异常:
org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:335) ~[postgresql-42.2.5.jar:42.2.5]
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:441) ~[postgresql-42.2.5.jar:42.2.5]
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:365) ~[postgresql-42.2.5.jar:42.2.5]
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:143) ~[postgresql-42.2.5.jar:42.2.5]
at org.postgresql.jdbc.PgPreparedStatement.execute(PgPreparedStatement.java:132) ~[postgresql-42.2.5.jar:42.2.5]
at com.zaxxer.hikari.pool.ProxyPreparedStatement.execute(ProxyPreparedStatement.java:44) ~[HikariCP-3.2.0.jar:na]
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.execute(HikariProxyPreparedStatement.java) ~[HikariCP-3.2.0.jar:na]
at org.jooq.tools.jdbc.DefaultPreparedStatement.execute(DefaultPreparedStatement.java:209) ~[jooq-3.11.9.jar:na]
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:432) ~[jooq-3.11.9.jar:na]
at org.jooq.impl.AbstractDMLQuery.execute(AbstractDMLQuery.java:613) ~[jooq-3.11.9.jar:na]
at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:350) ~[jooq-3.11.9.jar:na]
at org.jooq.impl.Tools$10$1.block(Tools.java:4377) ~[jooq-3.11.9.jar:na]
at java.base/java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3118) ~[na:na]
at org.jooq.impl.Tools$10.get(Tools.java:4374) ~[jooq-3.11.9.jar:na]
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1700) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(CompletableFuture.java:1692) ~[na:na]
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290) ~[na:na]
at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020) ~[na:na]
at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656) ~[na:na]
at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594) ~[na:na]
at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177) ~[na:na]
Caused by: java.io.EOFException: null
at org.postgresql.core.PGStream.receiveChar(PGStream.java:308) ~[postgresql-42.2.5.jar:42.2.5]
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1952) ~[postgresql-42.2.5.jar:42.2.5]
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:308) ~[postgresql-42.2.5.jar:42.2.5]
在大多数情况下,这也会将我的数据库设置为恢复模式。
在调度程序下次运行时,hikari 池会警告无法验证的连接:
HikariPool-1 - Failed to validate connection org.postgresql.jdbc.PgConnection@389c2816 (This connection has been closed.). Possibly consider using a shorter maxLifetime value.
我摆弄了 hikari 的
validation-timeout
和 max-lifetime
设置,但所有更改似乎都没有任何效果。
您可能在 Spring 应用程序和 PostgreSQL 数据库中遇到的问题似乎与连接管理有关,特别是与 HikariCP 连接池有关。 PSQLException 和随后的 EOFException 表明数据库连接存在意外关闭或终止的问题。发生这种情况的原因有多种,例如网络问题、数据库服务器问题或连接池中的配置问题。
我认为你应该检查 HikariCP 配置:
最大生命周期:将其设置为略小于数据库服务器连接超时的值会有所帮助。例如,如果您的数据库服务器在 30 分钟后连接超时,请将 HikariCP 的最大生命周期设置为 28 分钟之类的值。
验证超时:这是 HikariCP 在认为连接断开之前等待连接验证的最长时间。确保这个值是合理的。
空闲超时:此设置控制连接在池中可以空闲的最长时间。如果连接空闲时间超过此时间,HikariCP 将停用该连接。