Postgres: "ERRORE: il piano memorizzato nella cache non deve modificare il tipo di risultato"


115

Questa eccezione viene lanciata dal server PostgreSQL 8.3.7 alla mia applicazione. Qualcuno sa cosa significa questo errore e cosa posso fare al riguardo?

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

Puoi condividere la versione esatta di PostreSQL? 8.3.x?

Risposte:


190

Ho capito cosa stava causando questo errore.

La mia applicazione ha aperto una connessione al database e ha preparato un'istruzione SELECT per l'esecuzione.

Nel frattempo, un altro script stava modificando la tabella del database, cambiando il tipo di dati di una delle colonne restituite nell'istruzione SELECT precedente.

Ho risolto il problema riavviando l'applicazione dopo la modifica della tabella del database. Ciò ripristina la connessione al database, consentendo l'esecuzione dell'istruzione preparata senza errori.


4
Ho ottenuto questo su PostgreSQL 9.0.4, con Ruby on Rails 3.1-pre5. Sembra che questo dovrebbe essere gestito automaticamente da ActiveRecord, no?
docwhat

3
Sì, spero che ActiveRecord alla fine se ne occuperà. Credo che chiamare MyModel.reset_column_information risolverà le cose a breve termine se vuoi evitare il riavvio.
Grant Hutchins,

1
Ho sprecato un'ora per capire cosa fosse andato storto. La tua risposta mi ha salvato!
Sri Harsha Kappala

3
Sai che qualche soluzione non richiede il riavvio di tutte le applicazioni o del server postgres? Forse c'è qualche soluzione per cancellare manualmente il piano memorizzato nella cache quando si verifica l'errore?
Jacek Gzel

1
Ho avuto lo stesso problema su Postgres 10 durante l'esecuzione dei test JUnit per l'applicazione spring + jpa. Messaggio di eccezione: org.postgresql.util.PSQLException: ERROR: cached plan must not change result type. E tutti i test funzionano come un fascino, ma solo Repository.findById(). Non cambio lo schema nei miei test, ma lo sto usando @FlywayTestper preparare un database di inizializzazione del test per ogni test. Se rimuovo l' @FlywayTestannotazione, funziona bene.
Binakot

25

Sto aggiungendo questa risposta per chiunque atterri qui ERROR: cached plan must not change result typecercando su Google quando si tenta di risolvere il problema nel contesto di un'applicazione Java / JDBC.

Sono stato in grado di riprodurre in modo affidabile l'errore eseguendo aggiornamenti dello schema (cioè istruzioni DDL) mentre la mia app back-end che utilizzava il DB era in esecuzione. Se l'app stava interrogando una tabella che era stata modificata dall'aggiornamento dello schema (cioè l'app ha eseguito query prima e dopo l'aggiornamento su una tabella modificata), il driver postgres restituirebbe questo errore perché apparentemente memorizza nella cache alcuni dettagli dello schema.

Puoi evitare il problema configurando il tuo pgjdbcdriver con autosave=conservative. Con questa opzione, il driver sarà in grado di svuotare tutti i dettagli che sta memorizzando nella cache e non dovresti dover rimbalzare il tuo server o svuotare il tuo pool di connessioni o qualsiasi soluzione alternativa che potresti aver trovato.

Riprodotto su Postgres 9.6 (AWS RDS) e il mio test iniziale sembra indicare che il problema è stato completamente risolto con questa opzione.

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

Puoi guardare il pgjdbc numero 451 di Github per maggiori dettagli e cronologia del problema.


Gli utenti di JRuby ActiveRecords vedono questo: https://github.com/jruby/activerecord-jdbc-adapter/blob/master/lib/arjdbc/postgresql/connection_methods.rb#L60


Nota sulle prestazioni:

In base ai problemi di prestazioni segnalati nel collegamento sopra, dovresti eseguire alcuni test di prestazioni / carico / assorbimento della tua applicazione prima di attivarlo alla cieca.

Quando si esegue il test delle prestazioni sulla mia app in esecuzione su Postgres 10un'istanza AWS RDS , l'abilitazione conservativedell'impostazione comporta un utilizzo aggiuntivo della CPU sul server di database. Non era molto però, potevo anche vedere la autosavefunzionalità mostrata utilizzando una quantità misurabile di CPU dopo aver ottimizzato ogni singola query utilizzata dal mio test di carico e iniziato a spingere al massimo il test di carico.


7
Perché non è questa l'impostazione predefinita?
cdmckay

1
Funziona come pubblicizzato. I miei semplici test non hanno mostrato alcun impatto sulle prestazioni.
Samuli Pahaoja

1
come configurarlo con il driver Ruby Postgres?
Hrishi

@Hrishi Il tuo commento mi ha fatto capire che la domanda originale non specificava effettivamente Java (perché l'ho trovato quando ho affrontato il problema in un contesto Java). Direi che potresti voler pubblicare una domanda completamente nuova cercando esplicitamente una soluzione in un contesto Ruby.
Shorn

@cdmckay Perché è stata introdotta una nuova funzionalità nel driver intorno al timeframe della versione 9.4. Io per primo sarei molto infelice se una nuova versione di pgjdbc interrompesse la mia applicazione perché ha abilitato per impostazione predefinita nuove funzionalità non collaudate che riducono le prestazioni di cui non avevo bisogno. (Detto questo, questa è ora una nuova voce nella mia lista di controllo "fallo sempre quando crei una nuova applicazione").
Shorn

0

Per noi, stavamo affrontando un problema simile. La nostra applicazione funziona su più schemi. Ogni volta che stavamo apportando modifiche allo schema, questo problema ha iniziato a verificarsi.

L'impostazione del parametro prepareThreshold = 0 all'interno del parametro JDBC disabilita la memorizzazione nella cache delle istruzioni a livello di database. Questo l'ha risolto per noi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.