最简单的解决方法就是在你的连接字符串中添加
"prepareThreshold=0",如
this answer所示:
jdbc:postgresql://ip:port/db_name?prepareThreshold=0
或者,例如,如果您在连接字符串中使用了多个设置:
jdbc:postgresql://hostmaster.com:6432,hostsecond.com:6432/dbName?&targetServerType=master&prepareThreshold=0
这是一个众所周知的问题,当通过PgBouncer连接到PostgreSQL服务器时,而不是IntelliJ本身的问题。当将大量数据加载到数据库中时,IntelliJ将数据分成块并顺序加载它们,每次执行查询并提交数据。默认情况下,PostgreSQL在执行查询
5次后开始使用服务器端预准备语句。
使用PreparedStatement API时,默认情况下驱动程序使用服务器端准备语句。为了使用服务器端准备,您需要执行5次查询(可以通过prepareThreshold连接属性进行配置)。内部计数器跟踪语句已被执行的次数,当达到阈值时,它将开始使用服务器端准备语句。
可能您的PgBouncer使用事务池,并且最新版本的PbBouncer不支持
带事务池的准备语句。
如何在事务池中使用预处理语句?
要使预处理语句在此模式下工作,需要PgBouncer在内部跟踪它们,但它并没有这样做。因此,在客户端中禁用预处理语句是继续在此模式下使用PgBouncer的唯一方法。
您可以通过查看IntelliJ
日志文件来验证问题确实是由于与pgbouncer不正确使用预处理语句引起的。为此,请转到帮助->在资源管理器中显示日志,并搜索“org.postgresql.util.PSQLException:ERROR:prepared statement”异常。
2022-04-08 12:32:56,484 [693272684] WARN - j.database.dbimport.ImportHead - ERROR: prepared statement "S_3649" does not exist
java.sql.SQLException: ERROR: prepared statement "S_3649" does not exist
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2440)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2183)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:308)
at org.postgresql.jdbc.PgConnection.executeTransactionCommand(PgConnection.java:755)
at org.postgresql.jdbc.PgConnection.commit(PgConnection.java:777)