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
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
Câu trả lời:
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.
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.
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.
Đố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.