Postgres : "오류 : 캐시 된 계획은 결과 유형을 변경하면 안됩니다."


114

이 예외는 PostgreSQL 8.3.7 서버에서 내 응용 프로그램에 throw됩니다. 누구든지이 오류가 무엇을 의미하고 내가 그것에 대해 무엇을 할 수 있는지 알고 있습니까?

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
Ruby on Rails 3.1-pre5와 함께 PostgreSQL 9.0.4에서 이것을 얻었습니다. ActiveRecord에 의해 자동으로 처리되어야하는 것 같습니다.
docwhat

3
예, ActiveRecord가 결국이 문제를 해결하기를 바랍니다. 다시 시작하지 않으려면 MyModel.reset_column_information을 호출하면 단기적으로 문제가 해결 될 것이라고 생각합니다.
Grant Hutchins

1
나는 무엇이 잘못되었는지 알아 내기 위해 한 시간을 낭비했다. 당신의 대답은 나를 구했습니다!
스리랑카 Harsha에 Kappala

3
모든 응용 프로그램 또는 postgres 서버를 다시 시작할 필요가없는 솔루션이 있다는 것을 알고 있습니까? 오류가 발생할 때 캐시 된 계획을 수동으로 지우는 몇 가지 해결책이있을 수 있습니까?
제이 섹 Gzel

1
Spring + jpa 응용 프로그램에 대한 JUnit 테스트를 실행하는 동안 Postgres 10에서 동일한 문제가 발생했습니다. 예외 메시지 : org.postgresql.util.PSQLException: ERROR: cached plan must not change result type. 그리고 모든 테스트는 매력처럼 작동하지만 Repository.findById(). 테스트에서 스키마를 변경하지는 않지만 @FlywayTest각 테스트에 대해 테스트 초기화 데이터베이스를 준비하는 데 사용 하고 있습니다. @FlywayTest주석을 제거하면 잘 작동합니다.
Binakot

25

ERROR: cached plan must not change result typeJava / JDBC 응용 프로그램의 맥락에서 문제를 해결하려고 할 때 인터넷 검색을 통해 여기에 방문하는 모든 사람을 위해이 답변을 추가 하고 있습니다.

DB를 사용하는 백엔드 앱이 실행되는 동안 스키마 업그레이드 (예 : 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을 참조하십시오.


성능 참고 :

위 링크에서보고 된 성능 문제에 따라 맹목적으로 켜기 전에 애플리케이션의 성능 / 부하 / 흡수 테스트를 수행해야합니다.

AWS RDS Postgres 10인스턴스에서 실행되는 내 앱에서 성능 테스트를 수행 할 때 conservative설정을 활성화 하면 데이터베이스 서버에서 추가 CPU 사용량이 발생합니다. 그다지 많지는 않았지만 autosave부하 테스트에서 사용하는 모든 단일 쿼리를 조정하고 부하 테스트를 열심히 시작한 후에 측정 가능한 양의 CPU를 사용하는 것으로 기능이 나타나는 것을 볼 수있었습니다 .


7
이것이 기본값이 아닌 이유는 무엇입니까?
cdmckay

1
광고 된대로 작동합니다. 내 간단한 테스트는 성능에 어떤 영향도 미치지 않았습니다.
Samuli Pahaoja

1
Ruby Postgres 드라이버로 구성하는 방법은 무엇입니까?
Hrishi

@Hrishi 귀하의 의견은 원래 질문이 실제로 Java를 지정하지 않았다는 것을 깨달았습니다 (Java 컨텍스트에서 문제를 다룰 때 발견했기 때문에). Ruby 컨텍스트에서 솔루션을 명시 적으로 찾고 완전히 새로운 질문을 게시하고 싶을 수도 있습니다.
Shorn

@cdmckay 버전 9.4-ish 기간에 새로운 기능이 드라이버에 도입 되었기 때문입니다. pgjdbc의 일부 새 버전이 내 응용 프로그램을 망가 뜨린 경우 기본적으로 사용 가능한 새롭고 검증되지 않은 성능 저하 기능이 필요하지 않았기 때문에 나는 매우 불행 할 것입니다. (즉, 이것은 이제 "새 응용 프로그램을 만들 때 항상 수행"체크리스트의 새 항목입니다.)
Shorn

0

우리에게도 비슷한 문제가있었습니다. 우리의 응용 프로그램은 여러 스키마에서 작동합니다. 스키마를 변경할 때마다이 문제가 발생하기 시작했습니다.

JDBC 매개 변수 내에서 prepareThreshold = 0 매개 변수를 설정 하면 데이터베이스 수준에서 명령문 캐싱이 비활성화됩니다. 이것은 우리를 위해 그것을 해결했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.