2012-03-15 13 views
11

Tôi có một ứng dụng Java sử dụng cơ sở dữ liệu Postgres và tôi đang cố gắng giới thiệu PGPool để mở rộng cơ sở dữ liệu của tôi. Tôi đang gặp sự cố khi Postgres ném lỗi sau: unnamed prepared statement does not exist. Sau cranking lên khai thác gỗ trên Postgres tôi nhìn thấy những thứ sau đây xảy ra cho tất cả các tuyên bố chọn ứng dụng của tôi thực hiện:Các truy vấn Java chống lại PGPool II gây ra lỗi "không được đặt tên chuẩn bị không tồn tại" lỗi

EDTLOG: 00000: duration: 7.585 ms parse <unnamed>: "my select statement here" 
EDTLOG: 00000: duration: 0.088 ms bind <unnamed>: "my select statement here" 
EDTLOG: 00000: duration: 79.014 ms execute <unnamed>: "my select statement here" 

Nhưng đôi khi, giữa phân tích cú pháp/bind/thực hiện bước PGPool sẽ thực hiện một số truy vấn thêm, do đó các bản ghi trông giống như thế này:

EDTLOG: 00000: duration: 7.585 ms parse <unnamed>: "my select statement here" 
EDTLOG: 00000: duration: 0.088 ms bind <unnamed>: "my select statement here" 
EDTLOG: 00000: duration: 0.328 ms statement: SELECT count(*) FROM pg_class AS c, pg_namespace AS n WHERE c.relname = 'my_table' AND c.relnamespace = n.oid AND n.nspname = 'pg_catalog' 
EDTLOG: 00000: duration: 79.014 ms execute <unnamed>: "my select statement here" 
EDTERROR: 26000: unnamed prepared statement does not exist 
EDTLOG: 00000: duration: 0.022 ms parse S_2: ROLLBACK 
EDTLOG: 00000: duration: 0.005 ms bind S_2: ROLLBACK 
EDTLOG: 00000: duration: 0.008 ms execute S_2: ROLLBACK 

Từ những gì tôi hiểu, vì truy vấn không được đặt tên bởi Postgres nếu truy vấn khác đến trong phiên cơ sở dữ liệu đó trước khi truy vấn chưa đặt tên được thực thi. Vì vậy, vì PGPool đôi khi đưa ra các truy vấn bổ sung này giữa các bước phân tích cú pháp/liên kết/thực thi, nó làm cho truy vấn bị vứt đi.

Suy nghĩ đầu tiên của tôi là có lẽ ứng dụng Java của tôi không cần phải gửi câu lệnh phân tích cú pháp/liên kết/thực thi cho mọi truy vấn. Nhưng có vẻ như đây là hành vi mặc định cho trình điều khiển JDBC Postgres kể từ JDBC phiên bản 3 và Postgres 7.4 http://jdbc.postgresql.org/documentation/head/server-prepare.html. Tôi cho rằng tôi có thể thử hoàn toàn vô hiệu hóa các câu lệnh chuẩn bị phía máy chủ, nhưng tài liệu không chỉ rõ cách làm điều đó, và tôi không chắc đó là điều tôi muốn làm.

Suy nghĩ thứ hai của tôi là nhận PGPool II để ngừng gửi các truy vấn dữ liệu meta đó. Vì tôi chỉ cố gắng sử dụng PGPool như một bộ cân bằng tải, tôi không thực sự hiểu tại sao nó cần phải biết tất cả về siêu dữ liệu bảng của tôi. Có vẻ như PGPool muốn biết về các mối quan hệ bảng của tôi vì một lý do nào đó, và tiếc là tôi không thấy bất kỳ cách nào để vô hiệu hóa hành vi đó.

Bất kỳ thông tin chi tiết nào về cách giải quyết vấn đề này sẽ được đánh giá rất nhiều.

Một số thông tin về môi trường của tôi:

JDBC Driver: postgresql-9.1-901.jdbc4.jar 
Java version "1.6.0_31" 
Spring 3.1 managed JPA 
Hibernate 3.5 
Postgres 9.1 

UPDATE: Tôi tìm thấy một workaround cho vấn đề này. Bằng cách đặt protocolVersion=2 trong URL JDBC về cơ bản nó cho trình điều khiển JDBC Postgres không sử dụng các câu lệnh chuẩn bị phía máy chủ. Điều này cho phép ứng dụng của tôi chạy trong khi sử dụng PGPool II trước cơ sở dữ liệu của tôi. Tôi bị làm phiền bởi thực tế là tôi phải quay trở lại giao thức JDBC phiên bản 2 chỉ để sử dụng PGPool.

+0

@Zecas Vâng tôi biết cách trang web hoạt động, bạn không cần phải giải thích điều đó với tôi. Tôi vẫn không có một giải pháp cho phép tôi sử dụng phiên bản mới nhất của JDBC chống lại PGPool II. Theo như tôi lo ngại đây vẫn là một câu hỏi mở. –

+0

Bạn có thể muốn đảm bảo truy vấn của mình đang chạy bên trong giao dịch. Câu lệnh chuẩn bị sẽ bị loại bỏ nếu một giao dịch khác xuất hiện trên cùng một kết nối. Theo mặc định, trình điều khiển jdbc postgresql không sử dụng các giao dịch, có vẻ hơi lạ với tôi. Bạn có thể thiết lập hành vi giao dịch trong persistence.xml nếu tôi nhớ lại. – PlexQ

+0

Tại sao bạn sử dụng PgPool? Bạn không thể sử dụng DBCP, BoneCP hoặc c3p0 để quản lý trực tiếp hồ bơi kết nối từ bên trong ứng dụng của bạn? – Chochos

Trả lời

1

Tôi tìm thấy giải pháp cho vấn đề này. Bằng cách đặt protocolVersion = 2 trong URL JDBC về cơ bản nó cho trình điều khiển JDBC Postgres không sử dụng các câu lệnh được chuẩn bị phía máy chủ. Điều này cho phép ứng dụng của tôi chạy trong khi sử dụng PGPool II trước cơ sở dữ liệu của tôi. Tôi bị làm phiền bởi thực tế là tôi phải quay trở lại giao thức JDBC phiên bản 2 chỉ để sử dụng PGPool.

+2

Một tùy chọn khác để tránh các câu lệnh được chuẩn bị phía máy chủ sẽ là sử dụng tham số 'prepareThreshold' với số lần thực thi cao. –

-1

Điều gì sẽ xảy ra nếu bạn đặt tên cho câu lệnh đã chuẩn bị của mình?

Và một câu hỏi khác nảy sinh: Tại sao bạn sử dụng báo cáo đã chuẩn bị, nếu bạn không cần chúng?

Bạn có thể dễ dàng thực hiện các câu lệnh "bình thường" đối với trình điều khiển jdbc ...

+0

Tôi chỉ đang sử dụng các truy vấn JPA. Hibernate sau đó tạo các câu lệnh đã chuẩn bị và gửi chúng tới trình điều khiển JDBC. Tuy nhiên, từ những gì tôi đã đọc về trình điều khiển JDBC PostgreSQL, không có cách nào để thực hiện các câu lệnh được tham số hóa mà không sử dụng các câu lệnh được chuẩn bị. Và chúng ta hãy đối mặt với nó, tất cả các truy vấn đều có tham số. Và tôi không thể đặt tên các câu lệnh chuẩn bị vì tôi không phải là người tạo ra chúng, Hibernate là. –