开发人员说升级JDBC驱动后,很多SQL无法执行,查看数据库报错信息如下
2021-06-09 11:44:07.619 CST,"melotroom","melotroom",52308,"192.168.110.119:33768",54,131,"idle",2021-06-09 11:29:00 CST,4/0,0,ERROR,26000,"prepared statement ""S_84"" does not exist",,,,,,,,,"PostgreSQL JDBC Driver"
2021-06-09 11:44:07.914 CST,"melotroom","melotroom",38882,"192.168.110.119:33306",60c02eb1.97e2,781,"idle",2021-06-09 11:00:01 CST,9/0,0,ERROR,26000,"prepared statement ""S_85"" does not exist",,,,,,,,,"PostgreSQL JDBC Driver"
2021-06-09 11:44:07.915 CST,"melotroom","melotroom",38882,"192.168.110.119:33306",60c02eb1.97e2,782,"PARSE",2021-06-09 11:00:01 CST,9/2853710982,0,ERROR,42P05,"prepared statement ""S_86"" already exists",,,,,,"select
数据库使用环境用了pgbouncer,用的事物模式,发现事物模式不支持prepared statements
如果是session模式,可以设置erver_reset_query = DISCARD ALL; 或者至少设置 DEALLOCATE ALL。
如果需要在jdbc中禁用prepared statements,那么在连接串中设置prepareThreshold=0
prepared statements可以提升SQL的执行速度,原因如下:
- 它只发送语句句柄(例如S_1),而不是完整的SQL文本。
- 可使用二进制传输,参数和结果解析速度要快得多。
- 可重用服务端的执行计划。
- 客户端可以重用结果集列定义,因此不必在每次执行时接收和解析元数据。
会跟踪语句执行的次数,默认5次,也就是prepareThreshold=5.
总结:
所以在使用pgbouncer 事物模式的情况下,无法使用prepared statements,需要设置为如下:
jdbc.url=jdbc:postgresql://xxxxx:6431/xxxxx?prepareThreshold=0,但是这样设置每次都是硬解析了,无法绑定数据库服务端缓存的执行计划了。性能上会有损耗。
如果是会话模式,可以设置erver_reset_query = DISCARD ALL; 或者DEALLOCATE ALL。