org.postgresql.util.PSQLException: FATAL: xin lỗi, đã có quá nhiều khách hàng


93

Tôi đang cố gắng kết nối với cơ sở dữ liệu Postgresql, tôi gặp lỗi sau:

Lỗi: org.postgresql.util.PSQLException: FATAL: xin lỗi, đã có quá nhiều khách hàng

Lỗi có nghĩa là gì và làm cách nào để khắc phục?

server.propertiesTệp của tôi như sau:

serverPortData=9042
serverPortCommand=9078
trackConnectionURL=jdbc:postgresql://127.0.0.1:5432/vTrack?user=postgres password=postgres
dst=1
DatabaseName=vTrack
ServerName=127.0.0.1
User=postgres
Password=admin
MaxConnections=90
InitialConnections=80
PoolSize=100
MaxPoolSize=100
KeepAliveTime=100
TrackPoolSize=120
TrackMaxPoolSize=120
TrackKeepAliveTime=100
PortNumber=5432
Logging=1

Câu trả lời:


38

Chúng tôi không biết tệp server.properties đó là gì, chúng tôi cũng không biết SimocoPoolSize có nghĩa là gì (bạn phải không?)

Hãy đoán bạn đang sử dụng một số kết nối cơ sở dữ liệu tùy chỉnh. Sau đó, tôi đoán vấn đề là nhóm của bạn được định cấu hình để mở 100 hoặc 120 kết nối, nhưng máy chủ Postgresql của bạn được định cấu hình để chấp nhận MaxConnections=90. Những cài đặt này có vẻ khó hiểu. Hãy thử tăng lên MaxConnections=120.

Nhưng trước tiên bạn nên hiểu cơ sở hạ tầng lớp db của mình, biết bạn đang sử dụng pool nào, nếu bạn thực sự cần rất nhiều kết nối mở trong pool. Và, đặc biệt, nếu bạn trả lại các kết nối đã mở cho hồ bơi một cách duyên dáng


168

Giải thích về lỗi sau:

org.postgresql.util.PSQLException: FATAL: sorry, too many clients already.

Tóm lược:

Bạn đã mở nhiều hơn giới hạn cho phép của kết nối với cơ sở dữ liệu. Bạn đã chạy một cái gì đó như thế này: Connection conn = myconn.Open();bên trong một vòng lặp, và quên chạy conn.close();. Chỉ vì lớp của bạn bị phá hủy và rác được thu thập không giải phóng kết nối đến cơ sở dữ liệu. Cách khắc phục nhanh nhất cho vấn đề này là đảm bảo bạn có mã sau với bất kỳ lớp nào tạo kết nối:

protected void finalize() throws Throwable  
{  
    try { your_connection.close(); } 
    catch (SQLException e) { 
        e.printStackTrace();
    }
    super.finalize();  
}  

Đặt mã đó vào bất kỳ lớp nào bạn tạo Kết nối. Sau đó, khi lớp của bạn được thu gom rác, kết nối của bạn sẽ được giải phóng.

Chạy SQL này để xem các kết nối tối đa postgresql được phép:

show max_connections;

Giá trị mặc định là 100. PostgreSQL trên phần cứng tốt có thể hỗ trợ vài trăm kết nối cùng một lúc. Nếu bạn muốn có hàng nghìn, bạn nên cân nhắc sử dụng phần mềm gộp kết nối để giảm chi phí kết nối.

Hãy xem chính xác ai / cái gì / khi nào / ở đâu đang mở các kết nối của bạn:

SELECT * FROM pg_stat_activity;

Số lượng kết nối hiện được sử dụng là:

SELECT COUNT(*) from pg_stat_activity;

Chiến lược gỡ lỗi

  1. Bạn có thể cung cấp các tên người dùng / mật khẩu khác nhau cho các chương trình có thể không giải phóng kết nối để tìm ra nó là cái nào, sau đó tìm trong pg_stat_activity để tìm cái nào không được dọn dẹp sau chính nó.

  2. Thực hiện theo dõi ngăn xếp ngoại lệ đầy đủ khi không thể tạo kết nối và theo dõi mã sao lưu đến nơi bạn tạo mới Connection, đảm bảo mọi dòng mã nơi bạn tạo kết nối kết thúc bằngconnection.close();

Cách đặt max_connections cao hơn:

max_connections trong postgresql.conf đặt số lượng tối đa các kết nối đồng thời đến máy chủ cơ sở dữ liệu.

  1. Trước tiên hãy tìm tệp postgresql.conf của bạn
  2. Nếu bạn không biết nó ở đâu, hãy truy vấn cơ sở dữ liệu bằng sql: SHOW config_file;
  3. Của tôi là trong: /var/lib/pgsql/data/postgresql.conf
  4. Đăng nhập với tư cách người chủ và chỉnh sửa tệp đó.
  5. Tìm kiếm chuỗi: "max_connections".
  6. Bạn sẽ thấy một dòng cho biết max_connections=100.
  7. Đặt con số đó lớn hơn, kiểm tra giới hạn cho phiên bản postgresql của bạn.
  8. Khởi động lại cơ sở dữ liệu postgresql để các thay đổi có hiệu lực.

Max_connections tối đa là bao nhiêu?

Sử dụng truy vấn này:

select min_val, max_val from pg_settings where name='max_connections';

Tôi nhận được giá trị 8388607, về lý thuyết thì đó là số tiền nhiều nhất bạn được phép có, nhưng sau đó một quá trình chạy trốn có thể ăn hàng nghìn kết nối và thật ngạc nhiên, cơ sở dữ liệu của bạn không phản hồi cho đến khi khởi động lại. Nếu bạn có max_connections hợp lý như 100. Chương trình vi phạm sẽ bị từ chối kết nối mới.


4
tại sao một số người quên dấu ';' sau câu lệnh SQL ?! Làm cho sao chép và dán kéo :)
codervince

@codervince Bạn phải chú ý. Tôi gần như muốn nói rằng bạn nên phiên âm các lệnh hơn là sao chép + dán.
AVProgrammer

4

Không cần tăng MaxConnections & InitialConnections. Chỉ cần đóng các kết nối của bạn sau khi thực hiện công việc của bạn. Ví dụ: nếu bạn đang tạo kết nối:

try {
     connection = DriverManager.getConnection(
                    "jdbc:postgresql://127.0.0.1/"+dbname,user,pass);

   } catch (SQLException e) {
    e.printStackTrace();
    return;
}

Sau khi thực hiện công việc của bạn kết nối chặt chẽ:

try {
    connection.commit();
    connection.close();
} catch (SQLException e) {
    e.printStackTrace();
}

11
Luôn đóng các kết nối trong khối cuối cùng! Nếu không, kết nối vẫn mở nếu xảy ra lỗi.
tine2k

1

Các dòng vi phạm như sau:

MaxConnections=90
InitialConnections=80

Bạn có thể tăng các giá trị để cho phép nhiều kết nối hơn.


4
Và nếu bạn sẽ có nhiều kết nối hơn được phép, hãy điều chỉnh các thông số bộ nhớ để phù hợp với các kết nối tăng lên.
Kuberchaun

0

Bạn cần đóng tất cả các liên kết của mình, ví dụ: Nếu bạn thực hiện một câu lệnh CHÈN VÀO, bạn cần đóng câu lệnh và liên kết của mình theo cách này:

statement.close();
Connexion.close():

Và nếu bạn thực hiện một câu lệnh SELECT, bạn cần phải đóng câu lệnh, liên kết và tập kết quả theo cách này:

resultset.close();
statement.close();
Connexion.close();

Tôi đã làm điều này và nó hoạt động

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.