Postgres: “LỖI: kế hoạch đã lưu trong bộ nhớ cache không được thay đổi loại kết quả”


113

Ngoại lệ này đang được máy chủ PostgreSQL 8.3.7 ném vào ứng dụng của tôi. Có ai biết lỗi này có nghĩa là gì và tôi có thể làm gì với nó?

ERROR:  cached plan must not change result type
STATEMENT:  select code,is_deprecated from country where code=$1

Bạn có thể vui lòng chia sẻ phiên bản chính xác của PostreSQL không? 8,3.X?

Câu trả lời:


187

Tôi đã tìm ra nguyên nhân gây ra lỗi này.

Ứng dụng của tôi đã mở một kết nối cơ sở dữ liệu và chuẩn bị một câu lệnh SELECT để thực thi.

Trong khi đó, một tập lệnh khác đang sửa đổi bảng cơ sở dữ liệu, thay đổi kiểu dữ liệu của một trong các cột được trả về trong câu lệnh SELECT ở trên.

Tôi đã giải quyết vấn đề này bằng cách khởi động lại ứng dụng sau khi bảng cơ sở dữ liệu được sửa đổi. Điều này đặt lại kết nối cơ sở dữ liệu, cho phép câu lệnh đã chuẩn bị thực thi mà không có lỗi.


3
Tôi đã nhận được điều này trên PostgreSQL 9.0.4, với Ruby on Rails 3.1-pre5. Có vẻ như điều này sẽ được xử lý tự động bởi ActiveRecord, phải không?
docwhat

3
Vâng, tôi hy vọng rằng ActiveRecord cuối cùng sẽ giải quyết vấn đề này. Tôi tin rằng việc gọi MyModel.reset_column_information sẽ khắc phục mọi thứ trong thời gian ngắn nếu bạn muốn tránh khởi động lại.
Grant Hutchins

1
Tôi đã lãng phí một giờ để tìm ra những gì đã xảy ra. Câu trả lời của bạn đã cứu tôi!
Sri Harsha Kappala,

3
Bạn có biết giải pháp nào không yêu cầu khởi động lại tất cả ứng dụng hoặc máy chủ postgres không? Có thể có một số giải pháp để xóa kế hoạch lưu trong bộ nhớ cache theo cách thủ công khi lỗi xảy ra?
Jacek Gzel

1
Tôi gặp vấn đề tương tự trên Postgres 10 khi chạy thử nghiệm JUnit cho ứng dụng spring + jpa. Nhắn ngoại lệ: org.postgresql.util.PSQLException: ERROR: cached plan must not change result type. Và tất cả các thử nghiệm hoạt động như một sự quyến rũ, nhưng thôi Repository.findById(). Tôi không thay đổi lược đồ trong các thử nghiệm của mình, nhưng tôi đang sử dụng @FlywayTestđể chuẩn bị cơ sở dữ liệu init thử nghiệm cho mỗi thử nghiệm. Nếu tôi xóa @FlywayTestchú thích, nó hoạt động tốt.
Binakot

25

Tôi thêm câu trả lời này cho bất kỳ ai đến đây bằng cách sử dụng googling ERROR: cached plan must not change result typekhi cố gắng giải quyết vấn đề trong ngữ cảnh của ứng dụng Java / JDBC.

Tôi đã có thể tái tạo lỗi một cách đáng tin cậy bằng cách chạy nâng cấp giản đồ (tức là các câu lệnh DDL) trong khi ứng dụng back-end của tôi sử dụng DB đang chạy. Nếu ứng dụng đang truy vấn một bảng đã được thay đổi bởi nâng cấp giản đồ (tức là ứng dụng đã chạy các truy vấn trước và sau khi nâng cấp trên một bảng đã thay đổi) - trình điều khiển postgres sẽ trả về lỗi này vì rõ ràng nó thực hiện lưu vào bộ nhớ đệm của một số chi tiết lược đồ.

Bạn có thể tránh sự cố bằng cách định cấu hình pgjdbctrình điều khiển của mình với autosave=conservative. Với tùy chọn này, trình điều khiển sẽ có thể xóa bất kỳ chi tiết nào mà nó đang lưu vào bộ nhớ đệm và bạn không cần phải trả lại máy chủ hoặc xóa nhóm kết nối của bạn hoặc bất kỳ giải pháp nào mà bạn có thể đã đưa ra.

Được sao chép lại trên Postgres 9.6 (AWS RDS) và thử nghiệm ban đầu của tôi dường như cho thấy sự cố đã được giải quyết hoàn toàn với tùy chọn này.

Tài liệu: https://jdbc.postgresql.org/documentation/head/connect.html#connection-parameters

Bạn có thể xem pgjdbc số 451 trên Github để biết thêm chi tiết và lịch sử của vấn đề.


Người dùng JRuby ActiveRecords thấy điều này: https://github.com/jruby/activerecord-jdbc-adapter/blob/master/lib/arjdbc/postgresql/connection_methods.rb#L60


Lưu ý về hiệu suất:

Theo các vấn đề về hiệu suất được báo cáo trong liên kết trên - bạn nên thực hiện một số kiểm tra hiệu suất / tải / ngâm ứng dụng của mình trước khi bật tùy chọn này một cách mù quáng.

Khi thực hiện kiểm tra hiệu suất trên ứng dụng của riêng tôi chạy trên phiên bản AWS RDS Postgres 10, việc bật conservativecài đặt sẽ dẫn đến việc sử dụng thêm CPU trên máy chủ cơ sở dữ liệu. Mặc dù vậy, nó không nhiều lắm, tôi thậm chí chỉ có thể thấy autosavechức năng hiển thị như đang sử dụng một lượng CPU có thể đo được sau khi tôi đã điều chỉnh từng truy vấn đơn mà bài kiểm tra tải của tôi đang sử dụng và bắt đầu đẩy mạnh kiểm tra tải.


7
Tại sao đây không phải là mặc định?
cdmckay

1
Hoạt động như quảng cáo. Các bài kiểm tra đơn giản của tôi không cho thấy bất kỳ tác động nào về hiệu suất.
Samuli Pahaoja 14/09/18

1
làm thế nào để cấu hình nó với trình điều khiển Ruby Postgres?
Hrishi

@Hrishi Nhận xét của bạn khiến tôi nhận ra rằng câu hỏi ban đầu không thực sự chỉ định Java (vì tôi đã tìm thấy nó khi giải quyết vấn đề trong ngữ cảnh Java). Tôi muốn nói rằng bạn có thể muốn đăng một câu hỏi hoàn toàn mới một cách rõ ràng để tìm kiếm giải pháp trong ngữ cảnh Ruby.
Rút ngắn

@cdmckay Bởi vì đây là chức năng mới được đưa vào trình điều khiển trong khung thời gian phiên bản 9.4-ish. Tôi đối với một người sẽ rất không vui nếu một phiên bản pgjdbc mới nào đó đã phá vỡ ứng dụng của tôi vì nó mặc định bật chức năng làm giảm hiệu suất mới, chưa được chứng minh, mà tôi không cần. (Điều đó nói rằng, đây hiện là một mục mới trong danh sách kiểm tra "luôn làm điều này khi tạo ứng dụng mới" của tôi).
Rút ngắn

0

Đối với chúng tôi, chúng tôi đã phải đối mặt với vấn đề tương tự. Ứng dụng của chúng tôi hoạt động trên nhiều giản đồ. Bất cứ khi nào chúng tôi thực hiện các thay đổi giản đồ, vấn đề này bắt đầu xảy ra.

Thiết lập tham số readyThreshold = 0 bên trong tham số JDBC sẽ vô hiệu hóa bộ nhớ đệm câu lệnh ở cấp cơ sở dữ liệu. Điều này đã giải quyết nó cho chúng tôi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.