Postgres: "FEHLER: Der zwischengespeicherte Plan darf den Ergebnistyp nicht ändern."

113

Diese Ausnahme wird vom PostgreSQL 8.3.7-Server in meine Anwendung ausgelöst. Weiß jemand, was dieser Fehler bedeutet und was ich dagegen tun kann?

ERROR:  cached plan must not change result type
STATEMENT:  select code,is_deprecated from country where code=$1
Jin Kim
quelle
Können Sie bitte die genaue Version von PostreSQL teilen? 8.3.X?

Antworten:

187

Ich habe herausgefunden, was diesen Fehler verursacht hat.

Meine Anwendung hat eine Datenbankverbindung geöffnet und eine SELECT-Anweisung zur Ausführung vorbereitet.

In der Zwischenzeit änderte ein anderes Skript die Datenbanktabelle und änderte den Datentyp einer der Spalten, die in der obigen SELECT-Anweisung zurückgegeben wurden.

Ich habe dieses Problem behoben, indem ich die Anwendung neu gestartet habe, nachdem die Datenbanktabelle geändert wurde. Dadurch wird die Datenbankverbindung zurückgesetzt, sodass die vorbereitete Anweisung fehlerfrei ausgeführt werden kann.

Jin Kim
quelle
3
Ich habe dies auf PostgreSQL 9.0.4 mit Ruby on Rails 3.1-pre5 bekommen. Es scheint, dass dies automatisch von ActiveRecord erledigt werden sollte, nicht wahr?
docwhat
3
Ja, ich hoffe, dass ActiveRecord sich irgendwann darum kümmert. Ich glaube, dass das Aufrufen von MyModel.reset_column_information kurzfristig Abhilfe schafft, wenn Sie einen Neustart vermeiden möchten.
Grant Hutchins
1
Ich habe eine Stunde damit verbracht herauszufinden, was schief gelaufen ist. Deine Antwort hat mich gerettet!
Sri Harsha Kappala
3
Wissen Sie, dass für eine Lösung kein Neustart des gesamten Anwendungs- oder Postgres-Servers erforderlich ist? Vielleicht gibt es eine Lösung, um den zwischengespeicherten Plan manuell zu löschen, wenn der Fehler auftritt?
Jacek Gzel
1
Ich habe das gleiche Problem auf Postgres 10 beim Ausführen von JUnit-Tests für die Anwendung spring + jpa. Ausnahmemeldung : org.postgresql.util.PSQLException: ERROR: cached plan must not change result type. Und alle Tests funktionieren wie ein Zauber, aber nur Repository.findById(). Ich ändere das Schema in meinen Tests nicht, aber ich @FlywayTestbereite für jeden Test eine Testinitialdatenbank vor. Wenn ich @FlywayTestAnmerkungen entferne , funktioniert es gut.
Binakot
24

Ich füge diese Antwort für jeden hinzu, der hier landet, indem er googelt, ERROR: cached plan must not change result typewenn er versucht, das Problem im Kontext einer Java / JDBC-Anwendung zu lösen.

Ich konnte den Fehler zuverlässig reproduzieren, indem ich Schema-Upgrades (dh DDL-Anweisungen) ausführte, während meine Back-End-App, die die Datenbank verwendete, ausgeführt wurde. Wenn die App eine Tabelle abfragt, die durch das Schema-Upgrade geändert wurde (dh die App hat vor und nach dem Upgrade Abfragen für eine geänderte Tabelle ausgeführt), gibt der Postgres-Treiber diesen Fehler zurück, da anscheinend einige Schemadetails zwischengespeichert werden.

Sie können das Problem vermeiden, indem Sie Ihren pgjdbcTreiber mit konfigurieren autosave=conservative. Mit dieser Option kann der Treiber alle zwischengespeicherten Details löschen, und Sie sollten Ihren Server nicht bouncen oder Ihren Verbindungspool leeren müssen oder welche Problemumgehung Sie möglicherweise gefunden haben.

Wiedergabe auf Postgres 9.6 (AWS RDS) und meine ersten Tests scheinen darauf hinzudeuten, dass das Problem mit dieser Option vollständig behoben ist.

Dokumentation: https://jdbc.postgresql.org/documentation/head/connect.html#connection-parameters

Weitere Informationen und den Verlauf der Ausgabe finden Sie in der pgjdbc Github-Ausgabe 451 .


JRuby ActiveRecords-Benutzer sehen dies: https://github.com/jruby/activerecord-jdbc-adapter/blob/master/lib/arjdbc/postgresql/connection_methods.rb#L60


Hinweis zur Leistung:

Gemäß den im obigen Link gemeldeten Leistungsproblemen sollten Sie einige Leistungs- / Lade- / Einweich-Tests Ihrer Anwendung durchführen, bevor Sie diese blind einschalten.

Wenn Sie Leistungstests für meine eigene App durchführen, die auf einer AWS RDS- Postgres 10Instanz ausgeführt wird, führt das Aktivieren der conservativeEinstellung zu einer zusätzlichen CPU-Auslastung auf dem Datenbankserver. Es war jedoch nicht viel, ich konnte erst sehen, dass die autosaveFunktionalität eine messbare Menge an CPU verwendet, nachdem ich jede einzelne Abfrage, die mein Auslastungstest verwendete, optimiert und den Auslastungstest stark vorangetrieben hatte.

Geschoren
quelle
7
Warum ist das nicht die Standardeinstellung?
CDMckay
1
Funktioniert wie angegeben. Meine einfachen Tests zeigten keine Auswirkungen auf die Leistung.
Samuli Pahaoja
1
Wie konfiguriere ich es mit dem Ruby Postgres-Treiber?
Hrishi
@Hrishi Durch Ihren Kommentar wurde mir klar, dass in der ursprünglichen Frage Java nicht angegeben wurde (weil ich sie gefunden habe, als ich das Problem in einem Java-Kontext behandelt habe). Ich würde sagen, Sie möchten vielleicht eine ganz neue Frage stellen, die explizit nach einer Lösung in einem Ruby-Kontext sucht.
Geschoren am
@cdmckay Da es sich um eine neue Funktionalität handelte, die im Zeitrahmen von Version 9.4 in den Treiber eingeführt wurde. Ich jedenfalls wäre sehr unglücklich, wenn eine neue Version von pgjdbc meine Anwendung beschädigen würde, weil sie standardmäßig neue, nicht bewährte, leistungsmindernde Funktionen aktiviert, die ich nicht benötigte. (Das heißt, dies ist jetzt ein neuer Eintrag in meiner Checkliste "Immer beim Erstellen einer neuen Anwendung tun").
Geschoren am
0

Für uns standen wir vor einem ähnlichen Problem. Unsere Anwendung arbeitet mit mehreren Schemata. Wann immer wir Schemaänderungen vornahmen, trat dieses Problem auf.

Durch das Einrichten des Parameters prepareThreshold = 0 im JDBC-Parameter wird das Zwischenspeichern von Anweisungen auf Datenbankebene deaktiviert. Das hat es für uns gelöst.

irscomp
quelle