Postgres:“错误:缓存的计划不得更改结果类型”


113

PostgreSQL 8.3.7服务器向我的应用程序抛出了此异常。有谁知道该错误的含义以及对此我可以做什么?

ERROR:  cached plan must not change result type
STATEMENT:  select code,is_deprecated from country where code=$1

您能否分享PostreSQL的确切版本?8.3.X?

Answers:


187

我弄清楚是什么原因导致此错误。

我的应用程序打开了一个数据库连接,并准备了一条SELECT语句以供执行。

同时,另一个脚本正在修改数据库表,更改上述SELECT语句中返回的列之一的数据类型。

我通过修改数据库表后重新启动应用程序来解决此问题。这将重置数据库连接,从而使准备好的语句能够正确执行。


3
我在PostgreSQL 9.0.4和Ruby on Rails 3.1-pre5上获得了它。看来应该由ActiveRecord自动处理,不是吗?
docwhat 2011年

3
是的,我希望ActiveRecord最终会解决这个问题。我相信,如果要避免重新启动,则调用MyModel.reset_column_information可以在短期内解决问题。
格兰特·哈钦斯

1
我浪费了一个小时找出问题所在。您的回答救了我!
Sri Harsha Kappala '16

3
您知道任何解决方案都不需要重新启动所有应用程序或postgres服务器吗?也许有一些解决方案可以在发生错误时手动清除缓存的计划?
Jacek Gzel

1
在为spring + jpa应用程序运行JUnit测试时,在Postgres 10上遇到了相同的问题。异常消息:org.postgresql.util.PSQLException: ERROR: cached plan must not change result type。并且所有测试都像魅力一样,但仅限于Repository.findById()。我没有在测试中更改架构,但是我正在@FlywayTest为每个测试准备一个测试初始化​​数据库。如果删除@FlywayTest注释,则效果很好。
Binakot

25

ERROR: cached plan must not change result type在尝试解决Java / JDBC应用程序上下文中的问题时通过谷歌搜索着陆的人添加此答案。

当我使用DB的后端应用程序正在运行时,通过运行模式升级(即DDL语句),我能够可靠地重现该错误。如果应用程序正在查询已被架构升级更改的表(即,应用程序在已更改表的升级之前和之后运行查询)-postgres驱动程序将返回此错误,因为显然它确实缓存了某些架构详细信息。

您可以通过使用配置pgjdbc驱动程序来避免此问题autosave=conservative。使用此选项,驱动程序将能够刷新其缓存的任何详细信息,并且您不必弹跳服务器或刷新连接池或您可能想出的任何解决方法。

转载于Postgres 9.6(AWS RDS),我的初步测试似乎表明使用此选项可以完全解决问题。

说明文件: https //jdbc.postgresql.org/documentation/head/connect.html#connection-parameters

您可以查看pgjdbc Github第451期,以了解更多详细信息和历史记录。


JRuby ActiveRecords用户可以看到以下内容:https : //github.com/jruby/activerecord-jdbc-adapter/blob/master/lib/arjdbc/postgresql/connection_methods.rb#L60


关于性能的注意事项:

根据上面链接中报告的性能问题-您应该对应用程序进行一些性能/负载/浸泡测试,然后再盲目打开。

在运行于AWS RDS Postgres 10实例上的我自己的应用程序上进行性能测试时,启用该conservative设置确实会导致数据库服务器上额外的CPU使用率。虽然不多,但autosave在调整负载测试正在使用的每个查询并开始努力推动负载测试之后,我什至只能看到功能显示为使用了可测量的CPU。


7
为什么这不是默认值?
cdmckay,

1
按照广告作品。我的简单测试未显示任何性能影响。
Samuli Pahaoja

1
如何使用Ruby Postgres驱动程序进行配置?
赫里希

@Hrishi您的评论使我意识到原来的问题实际上并未指定Java(因为我是在Java上下文中处理该问题时发现的)。我想说,您可能想发布一个全新的问题,以便在Ruby上下文中寻找解决方案。
Shorn

@cdmckay因为它是驱动程序在9.4版左右的时间范围内引入的新功能。如果某个新版本的pgjdbc破坏了我的应用程序,我会很不高兴,因为它默认启用了我不需要的,未经验证的,性能下降的新功能。(也就是说,这是我“在创建新应用程序时始终执行此操作”清单上的新条目)。
Shorn

0

对于我们来说,我们面临着类似的问题。我们的应用程序可以在多个架构上运行。每当我们进行架构更改时,此问题就会开始出现。

在JDBC参数中设置prepareThreshold = 0参数将在数据库级别禁用语句缓存。这为我们解决了。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.