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?

回答:


187

私はこのエラーの原因を突き止めました。

アプリケーションでデータベース接続を開き、実行するSELECTステートメントを準備しました。

一方、別のスクリプトがデータベーステーブルを変更し、上記のSELECTステートメントで返される列の1つのデータ型を変更していました。

データベーステーブルが変更された後にアプリケーションを再起動することで、これを解決しました。これにより、データベース接続がリセットされ、準備されたステートメントをエラーなしで実行できます。


3
これはPostgreSQL 9.0.4で、Ruby on Rails 3.1-pre5で入手できました。これはActiveRecordによって自動的に処理されるべきだと思いますか?
docwhat 2011

3
ええ、私はActiveRecordが最終的にこれを処理することを願っています。再起動を避けたい場合は、MyModel.reset_column_informationを呼び出すと、短期的には問題が解決すると思います。
Grant Hutchins

1
何が悪いのかを理解するのに1時間無駄にした。あなたの答えは私を救った!
スリハルシャカパラ16

3
すべてのアプリケーションまたはpostgresサーバーを再起動する必要のない解決策を知っていますか?おそらく、エラーが発生したときにキャッシュされたプランを手動でクリアするための解決策はありますか?
Jacek Gzel 2017年

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 typeJava / 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 2018年

1
宣伝通りに動作します。私の簡単なテストでは、パフォーマンスへの影響はありませんでした。
Samuli Pahaoja 2018

1
Ruby Postgresドライバーでそれを構成する方法?
Hrishi

@Hrishiあなたのコメントにより、元の質問は実際にはJavaを指定していないことがわかりました(Javaコンテキストで問題を処理するときに見つけたためです)。Rubyのコンテキストで解決策を明確に探すまったく新しい質問を投稿したいと思うかもしれません。
ソーン

@cdmckayバージョン9.4のような時間枠でドライバーに導入された新機能だったからです。pgjdbcのいくつかの新しいバージョンが、デフォルトで有効化された、証明されていない、パフォーマンスを低下させる不要な機能を有効にしたため、アプリケーションが壊れた場合、私は非常に不幸です。(とはいえ、これは私の「新しいアプリケーションを作成するときは常にこれを行う」チェックリストの新しいエントリです)。
ソーン

0

私たちにとっても、同様の問題に直面していました。このアプリケーションは複数のスキーマで動作します。スキーマの変更を行うたびに、この問題が発生し始めました。

JDBCパラメータ内でprepareThreshold = 0パラメータを設定すると、データベースレベルでのステートメントキャッシングが無効になります。これで解決しました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.