Postgres: «ОШИБКА: кешированный план не должен изменять тип результата»

115

Это исключение создается сервером 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?

Ответы:

190

Я понял, что вызвало эту ошибку.

Мое приложение открыло соединение с базой данных и подготовило оператор SELECT для выполнения.

Тем временем другой сценарий изменял таблицу базы данных, изменяя тип данных одного из столбцов, возвращаемых в приведенном выше операторе SELECT.

Я решил эту проблему, перезапустив приложение после изменения таблицы базы данных. Это сбрасывает соединение с базой данных, позволяя подготовленному оператору выполняться без ошибок.

Джин Ким
источник
4
Я получил это на PostgreSQL 9.0.4 с Ruby on Rails 3.1-pre5. Похоже, это должно обрабатываться ActiveRecord автоматически, не так ли?
docwhat 07
3
Да, я надеюсь, что ActiveRecord со временем позаботится об этом. Я считаю, что вызов MyModel.reset_column_information исправит ситуацию в краткосрочной перспективе, если вы хотите избежать перезапуска.
Грант Хатчинс,
1
Я потратил час, выясняя, что пошло не так. Ваш ответ спас меня!
Шри Харша Каппала
3
Знаете ли вы, что какое-либо решение не требует перезапуска всего приложения или сервера postgres? Может, есть какое-то решение, чтобы вручную очистить кешированный план при возникновении ошибки?
Яцек Гзель
1
У меня такая же проблема с Postgres 10 при запуске тестов JUnit для приложения spring + jpa. Сообщение об исключении: org.postgresql.util.PSQLException: ERROR: cached plan must not change result type. И все тесты работают как шарм, но только Repository.findById(). Я не меняю схему в своих тестах, но я использую @FlywayTestдля подготовки базы данных инициализации теста для каждого теста. Если я удалю @FlywayTestаннотацию, все будет хорошо.
Binakot
25

Я добавляю этот ответ для всех, кто попадает сюда, используя поиск в Google 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 выпуск 451 Github для получения более подробной информации и истории проблемы.


Пользователи JRuby ActiveRecords видят это: https://github.com/jruby/activerecord-jdbc-adapter/blob/master/lib/arjdbc/postgresql/connection_methods.rb#L60


Примечание по производительности:

Согласно сообщениям о проблемах с производительностью в приведенной выше ссылке - вам следует провести некоторое тестирование производительности / нагрузки / выдержки вашего приложения, прежде чем включать его вслепую.

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

Shorn
источник
7
Почему это не по умолчанию?
cdmckay
1
Работает как рекламируется. Мои простые тесты не показали никакого влияния на производительность.
Самули Пахаоджа
1
как настроить его с помощью драйвера Ruby Postgres?
Hrishi
@Hrishi Ваш комментарий заставил меня понять, что исходный вопрос на самом деле не указывал на Java (потому что я обнаружил его при решении проблемы в контексте Java). Я бы сказал, что вы, возможно, захотите опубликовать совершенно новый вопрос, явно ищущий решение в контексте Ruby.
Shorn
@cdmckay Потому что это была новая функциональность, введенная в драйвер примерно в период времени версии 9.4. Я, например, был бы очень недоволен, если бы какая-то новая версия pgjdbc сломала мое приложение, потому что в нем по умолчанию были включены новые, непроверенные функции, снижающие производительность, которые мне не нужны. (Тем не менее, теперь это новая запись в моем контрольном списке «всегда делайте это при создании нового приложения»).
Shorn
0

Для нас мы столкнулись с аналогичной проблемой. Наше приложение работает с несколькими схемами. Эта проблема возникала всякий раз, когда мы вносили изменения в схему.

Установка параметра prepareThreshold = 0 внутри параметра JDBC отключает кеширование операторов на уровне базы данных. Это решило проблему для нас.

irscomp
источник