Постгреси: "ПОМИЛКА: кешований план не повинен змінювати тип результату"


114

Цей виняток передається сервером 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?

Відповіді:


189

Я зрозумів, що викликає цю помилку.

Мій додаток відкрив підключення до бази даних та підготував операцію SELECT для виконання.

Тим часом, інший скрипт модифікував таблицю бази даних, змінюючи тип даних одного з стовпців, що повертаються у вищевказаному операторі SELECT.

Я вирішив це шляхом перезавантаження програми після зміни таблиці баз даних. Це скидає підключення до бази даних, дозволяючи підготовленому оператору виконуватись без помилок.


4
Я отримав це на PostgreSQL 9.0.4, з Ruby on Rails 3.1-pre5. Здається, що ActiveRecord це повинен вирішувати автоматично, ні?
док

3
Так, я сподіваюся, що ActiveRecord врешті подбає про це. Я вважаю, що виклик MyModel.reset_column_information виправить речі за короткий термін, якщо ви хочете уникнути перезавантаження.
Грант Хатчінс

1
Я витратив годину, з'ясовуючи, що пішло не так. Ваша відповідь мене врятувала!
Шрі Харша Каппала

3
Чи знаєте ви, що будь-яке рішення не потребує перезавантаження всього сервера додатків або postgres? Можливо, є якесь рішення для очищення кешованого плану вручну, коли виникає помилка?
Jacek Gzel

1
Я отримав таку ж проблему на Postgres 10 під час запуску тестів JUnit для програми Spring + jpa. Повідомлення про виключення: org.postgresql.util.PSQLException: ERROR: cached plan must not change result type. І всі тести працюють як шарм, але тільки Repository.findById(). Я не змінюю схему в своїх тестах, але я використовую @FlywayTestдля підготовки тестової бази даних для кожного тесту. Якщо я видаляю @FlywayTestпримітку, вона працює добре.
Бінакот

25

Я додаю цю відповідь для тих, хто приземлився сюди, гуглюючи ERROR: cached plan must not change result typeпри спробі вирішити проблему в контексті програми Java / JDBC.

Мені вдалося надійно відтворити помилку, запустивши оновлення схеми (тобто операторів 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


Примітка про продуктивність:

Відповідно до повідомлених проблем щодо продуктивності у вищенаведеному посиланні - перед тим, як увімкнути цю операцію, слід пройти тестування на роботу / завантаження / замочування.

Проводячи тестування продуктивності мого власного додатка, що працює на Postgres 10екземплярі AWS RDS , включення conservativeналаштування призводить до додаткового використання процесора на сервері баз даних. Хоча це було не так багато, я навіть міг навіть побачити, як autosaveфункціональність відображається як використання вимірюваної кількості процесора після того, як я налаштував кожен запит, який використовував мій тест навантаження, і почав наполягати навантажувальний тест.


7
Чому це не за замовчуванням?
cdmckay

1
Працює як рекламується. Мої прості тести не показали жодного впливу на продуктивність.
Самулі Пахаоя

1
як налаштувати його за допомогою драйвера Ruby Postgres?
Хріші

@Hrishi Ваш коментар змусив мене зрозуміти, що в оригінальному запитанні насправді не було вказано Java (тому що я знайшов її, коли вирішував проблему в контексті Java). Я б сказав, що ви можете поставити зовсім нове запитання, явно шукаючи рішення в контексті Рубі.
Шорн

@cdmckay Тому, що це була нова функціональність, введена в драйвер приблизно в часовій рамці версії 9.4-ish. Я, наприклад, був би дуже незадоволений, якби якась нова версія pgjdbc зламала мою програму, тому що в ній не потрібна нова, не доведена функціональність, що знижує продуктивність, яка мені не потрібна. (Однак, це новий запис у моєму списку "завжди роби це під час створення нового додатка").
Шорн

0

Для нас перед нами було подібне питання. Наш додаток працює за кількома схемами. Щоразу, коли ми вносили зміни до схеми, ця проблема почала виникати.

Налаштування параметра PrepaThreshold = 0 всередині параметра JDBC вимикає кешування операторів на рівні бази даних. Це вирішило це за нас.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.