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

3
ใช่ฉันหวังว่า ActiveRecord จะดูแลเรื่องนี้ในที่สุด ฉันเชื่อว่าการเรียก MyModel.reset_column_information จะแก้ไขสิ่งต่างๆได้ในระยะสั้นหากคุณต้องการหลีกเลี่ยงการรีสตาร์ท
Grant Hutchins

1
ฉันเสียเวลาไปหนึ่งชั่วโมงเพื่อหาสิ่งที่ผิดพลาด คำตอบของคุณช่วยฉันไว้!
Sri Harsha Kappala

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คำอธิบายประกอบก็ใช้ได้ดี
Binakot

25

ฉันกำลังเพิ่มคำตอบนี้สำหรับทุกคนที่ลงจอดที่นี่โดย googling ERROR: cached plan must not change result typeเมื่อพยายามแก้ปัญหาในบริบทของแอปพลิเคชัน Java / JDBC

ฉันสามารถสร้างข้อผิดพลาดซ้ำได้อย่างน่าเชื่อถือโดยเรียกใช้การอัปเกรดสคีมา (เช่นคำสั่ง DDL) ในขณะที่แอปแบ็คเอนด์ที่ใช้ DB กำลังทำงานอยู่ หากแอปกำลังค้นหาตารางที่มีการเปลี่ยนแปลงโดยการอัปเกรดสคีมา (กล่าวคือแอปเรียกใช้การสืบค้นก่อนและหลังการอัปเกรดบนตารางที่เปลี่ยนแปลง) - โปรแกรมควบคุม 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ตั้งค่าจะส่งผลให้มีการใช้งาน CPU มากขึ้นบนเซิร์ฟเวอร์ฐานข้อมูล แม้ว่าจะไม่มากนัก แต่ฉันสามารถเห็นautosaveฟังก์ชันการทำงานที่แสดงขึ้นว่าใช้ CPU ในปริมาณที่วัดได้หลังจากที่ฉันได้ปรับแต่งแบบสอบถามทุกครั้งที่ใช้การทดสอบโหลดของฉันและเริ่มทำการทดสอบการโหลดอย่างหนัก


7
เหตุใดจึงไม่เป็นค่าเริ่มต้น
cdmckay

1
ทำงานได้ตามที่โฆษณา การทดสอบอย่างง่ายของฉันไม่ได้แสดงผลกระทบด้านประสิทธิภาพ
Samuli Pahaoja

1
วิธีกำหนดค่าด้วยไดรเวอร์ Ruby Postgres
Hrishi

@Hrishi ความคิดเห็นของคุณทำให้ฉันรู้ว่าคำถามเดิมไม่ได้ระบุ Java จริงๆ (เพราะฉันพบมันเมื่อจัดการกับปัญหาในบริบท Java) ฉันบอกว่าคุณอาจต้องการโพสต์คำถามใหม่ทั้งหมดโดยมองหาวิธีแก้ปัญหาในบริบท Ruby อย่างชัดเจน
ตัด

@cdmckay เนื่องจากเป็นฟังก์ชันใหม่ที่นำมาใช้กับไดรเวอร์ในช่วงเวลา 9.4-ish ฉันสำหรับคนหนึ่งจะไม่มีความสุขมากถ้า pgjdbc เวอร์ชันใหม่บางแอปพลิเคชันของฉันพังเพราะเป็นค่าเริ่มต้นที่เปิดใช้งานฟังก์ชันใหม่ที่ไม่ได้รับการพิสูจน์และลดประสิทธิภาพที่ฉันไม่ต้องการ (ที่กล่าวว่าตอนนี้เป็นรายการใหม่ในรายการตรวจสอบ "ทำสิ่งนี้เสมอเมื่อสร้างแอปพลิเคชันใหม่")
ตัด

0

สำหรับเราเราประสบปัญหาที่คล้ายกัน แอปพลิเคชันของเราทำงานกับสคีมาหลายแบบ เมื่อใดก็ตามที่เราทำการเปลี่ยนแปลงสคีมาปัญหานี้ก็เริ่มเกิดขึ้น

การตั้งค่าพารามิเตอร์prepThreshold = 0ภายในพารามิเตอร์ JDBC ปิดใช้งานการแคชคำสั่งที่ระดับฐานข้อมูล สิ่งนี้แก้ไขได้สำหรับเรา

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.