Postgres: “ERROR: cache plan tidak boleh mengubah jenis hasil”

115

Pengecualian ini dilemparkan oleh server PostgreSQL 8.3.7 ke aplikasi saya. Adakah yang tahu apa arti kesalahan ini dan apa yang dapat saya lakukan?

ERROR:  cached plan must not change result type
STATEMENT:  select code,is_deprecated from country where code=$1
Jin Kim
sumber
Bisakah Anda membagikan versi PostreSQL yang tepat? 8.3.X?

Jawaban:

190

Saya menemukan apa yang menyebabkan kesalahan ini.

Aplikasi saya membuka koneksi database dan menyiapkan pernyataan SELECT untuk dieksekusi.

Sementara itu, skrip lain sedang memodifikasi tabel database, mengubah tipe data dari salah satu kolom yang dikembalikan dalam pernyataan SELECT di atas.

Saya menyelesaikan ini dengan memulai ulang aplikasi setelah tabel database diubah. Ini mengatur ulang koneksi database, memungkinkan pernyataan yang disiapkan untuk dijalankan tanpa kesalahan.

Jin Kim
sumber
4
Saya mendapatkan ini di PostgreSQL 9.0.4, dengan Ruby on Rails 3.1-pre5. Sepertinya ini harus ditangani secara otomatis oleh ActiveRecord, bukan?
docwhat
3
Ya, saya harap ActiveRecord pada akhirnya akan menangani masalah ini. Saya percaya bahwa memanggil MyModel.reset_column_information akan memperbaiki banyak hal dalam jangka pendek jika Anda ingin menghindari memulai ulang.
Grant Hutchins
1
Saya membuang waktu satu jam untuk mencari tahu apa yang salah. Jawaban Anda menyelamatkan saya!
Sri Harsha Kappala
3
Apakah Anda tahu ada solusi yang tidak memerlukan restart semua aplikasi atau server postgres? Mungkin ada beberapa solusi untuk menghapus paket cache secara manual saat terjadi kesalahan?
Jacek Gzel
1
Saya mendapat masalah yang sama di Postgres 10 saat menjalankan tes JUnit untuk aplikasi musim semi + jpa. Pesan pengecualian: org.postgresql.util.PSQLException: ERROR: cached plan must not change result type. Dan semua tes bekerja seperti pesona, tetapi hanya Repository.findById(). Saya tidak mengubah skema dalam pengujian saya, tetapi saya menggunakan @FlywayTestuntuk menyiapkan database init pengujian untuk setiap pengujian. Jika saya menghapus @FlywayTestanotasi, itu berfungsi dengan baik.
Binakot
25

Saya menambahkan jawaban ini untuk siapa pun yang mendarat di sini dengan googling ERROR: cached plan must not change result typeketika mencoba menyelesaikan masalah dalam konteks aplikasi Java / JDBC.

Saya dapat mereproduksi kesalahan secara andal dengan menjalankan pemutakhiran skema (yaitu pernyataan DDL) sementara aplikasi back-end saya yang menggunakan DB sedang berjalan. Jika aplikasi meminta tabel yang telah diubah oleh pemutakhiran skema (yaitu aplikasi menjalankan kueri sebelum dan sesudah pemutakhiran pada tabel yang diubah) - driver postgres akan mengembalikan kesalahan ini karena tampaknya itu melakukan caching pada beberapa detail skema.

Anda dapat menghindari masalah dengan mengkonfigurasi pgjdbcdriver Anda denganautosave=conservative . Dengan opsi ini, driver akan dapat membersihkan detail apa pun yang sedang di-cache dan Anda tidak perlu memantulkan server Anda atau mengosongkan kumpulan koneksi Anda atau solusi apa pun yang mungkin Anda temukan.

Direproduksi pada Postgres 9.6 (AWS RDS) dan pengujian awal saya tampaknya menunjukkan bahwa masalah telah diselesaikan sepenuhnya dengan opsi ini.

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

Anda dapat melihat pgjdbc Github masalah 451 untuk detail lebih lanjut dan riwayat masalah tersebut.


Pengguna JRuby ActiveRecords melihat ini: https://github.com/jruby/activerecord-jdbc-adapter/blob/master/lib/arjdbc/postgresql/connection_methods.rb#L60


Catatan tentang kinerja:

Sesuai dengan masalah kinerja yang dilaporkan pada tautan di atas - Anda harus melakukan beberapa pengujian kinerja / beban / rendam aplikasi Anda sebelum mengaktifkannya secara membabi buta.

Saat melakukan pengujian kinerja pada aplikasi saya sendiri yang berjalan pada Postgres 10instans AWS RDS , mengaktifkan conservativepengaturan tersebut mengakibatkan penggunaan CPU tambahan pada server database. Namun itu tidak banyak, saya bahkan hanya bisa melihat autosavefungsinya muncul sebagai menggunakan jumlah CPU yang dapat diukur setelah saya menyetel setiap kueri yang digunakan uji beban saya dan mulai mendorong uji beban dengan keras.

Shorn
sumber
7
Mengapa ini bukan default?
cdmckay
1
Bekerja seperti yang diiklankan. Pengujian sederhana saya tidak menunjukkan dampak kinerja apa pun.
Samuli Pahaoja
1
bagaimana cara mengkonfigurasinya dengan driver Ruby Postgres?
Hrishi
@Hrishi Komentar Anda membuat saya menyadari bahwa pertanyaan asli sebenarnya tidak menyebutkan Java (karena saya menemukannya saat menangani masalah dalam konteks Java). Saya akan mengatakan Anda mungkin ingin memposting pertanyaan baru secara eksplisit mencari solusi dalam konteks Ruby.
Dicukur
@cdmckay Karena ini adalah fungsionalitas baru yang diperkenalkan ke driver sekitar jangka waktu versi 9.4-ish. Saya untuk satu orang akan sangat tidak senang jika beberapa versi baru pgjdbc merusak aplikasi saya karena itu secara default mengaktifkan fungsi penurunan kinerja baru, tidak terbukti, dan tidak saya perlukan. (Yang mengatakan, ini sekarang entri baru pada daftar periksa "selalu lakukan ini saat membuat aplikasi baru").
Dicukur
0

Bagi kami, kami menghadapi masalah serupa. Aplikasi kami bekerja pada banyak skema. Setiap kali kami melakukan perubahan skema, masalah ini mulai muncul.

Menyiapkan parameter preparedThreshold = 0 di dalam parameter JDBC menonaktifkan cache pernyataan di tingkat database. Ini menyelesaikannya untuk kami.

irscomp
sumber