Có thời gian chờ cho các kết nối PostgreSQL nhàn rỗi không?


94
1 S postgres  5038   876  0  80   0 - 11962 sk_wai 09:57 ?        00:00:00 postgres: postgres my_app ::1(45035) idle                                                                                 
1 S postgres  9796   876  0  80   0 - 11964 sk_wai 11:01 ?        00:00:00 postgres: postgres my_app ::1(43084) idle             

Tôi thấy rất nhiều người trong số họ. Chúng tôi đang cố gắng sửa lỗi rò rỉ kết nối của mình. Nhưng trong khi đó, chúng tôi muốn đặt thời gian chờ cho các kết nối không hoạt động này, có thể tối đa là 5 phút.


bạn đang kết nối với DB như thế nào? socketTimeout có thể là thứ bạn đang tìm kiếm.
Doon

Chúng tôi có ứng dụng web Pylons kế thừa này và chúng tôi đã sử dụng SQLAlchemy nhưng rõ ràng là chúng tôi đã không sử dụng nó đúng cách. Tôi không nhớ. Chúng tôi đang cố gắng khắc phục sự cố rò rỉ. socketTimeouttừ tài liệu, có vẻ như điều này sẽ đóng hoàn toàn kết nối với DB. Tôi đang cố gắng đóng từng trạng thái không hoạt động và bộ đếm bắt đầu ngay sau khi kết nối được thiết lập.
user1012451 5/11/12


@ user1012451 Khi bạn nói "đóng từng phiên không hoạt động" - có phải ý bạn là chấm dứt <IDLE> in transactionphiên, để phiên đang chạy nhưng ở <IDLE>trạng thái? Nói cách khác, chấm dứt giao dịch nhưng không phải phiên giao dịch? (Phản đối: câu hỏi không rõ ràng)
Craig Ringer

@CraigRinger sau một thời gian, chúng tôi đạt được kết nối khách hàng tối đa. Để giải quyết điều đó, chúng ta phải khởi động lại ứng dụng web, điều này buộc phải khởi động lại postgresql. Điều đó xóa sạch mọi kết nối. Khi chúng tôi nhìn thấy những điều này idlemãi mãi, chúng tôi đang hỏi liệu chúng tôi có thể đặt thời gian chờ cho mỗi kết nối / phiên (thành thật mà nói, tôi không biết thuật ngữ chính xác, xin lỗi). Nếu một giao dịch mất 5 phút cho một cái gì đó ứng dụng web bình thường phải là sai ....
user1012451

Câu trả lời:


118

Có vẻ như bạn bị rò rỉ kết nối trong ứng dụng của mình vì nó không thể đóng các kết nối tổng hợp . Bạn không gặp vấn đề chỉ với<idle> in transaction các phiên mà về tổng thể có quá nhiều kết nối.

Loại bỏ kết nối không phải là câu trả lời thích hợp cho điều đó, nhưng đó là một giải pháp tạm thời ổn.

Thay vì khởi động lại PostgreSQL để khởi động tất cả các kết nối khác khỏi cơ sở dữ liệu PostgreSQL, hãy xem: Làm cách nào để tách tất cả người dùng khác khỏi cơ sở dữ liệu postgres? Làm thế nào để loại bỏ một cơ sở dữ liệu PostgreSQL nếu có các kết nối đang hoạt động với nó?. Sau đó hiển thị một truy vấn tốt hơn.

Để đặt thời gian chờ, như @Doon đã đề xuất, hãy xem Cách tự động đóng các kết nối không hoạt động trong PostgreSQL? , khuyên bạn nên sử dụng PgBouncer để proxy cho PostgreSQL và quản lý các kết nối nhàn rỗi. Đây là một ý tưởng rất hay nếu bạn có một ứng dụng bị lỗi làm rò rỉ kết nối; Tôi thực sự khuyên bạn nên định cấu hình PgBouncer.

Một lưu trữ TCP sẽ không thực hiện công việc ở đây, bởi vì ứng dụng vẫn được kết nối và tồn tại, điều đó không nên xảy ra.

Trong PostgreSQL 9.2 trở lên, bạn có thể sử dụng state_changecột dấu thời gian mới và statetrường pg_stat_activityđể triển khai máy gặt kết nối nhàn rỗi. Có một công việc cron chạy một cái gì đó như thế này:

SELECT pg_terminate_backend(pid)
    FROM pg_stat_activity
    WHERE datname = 'regress'
      AND pid <> pg_backend_pid()
      AND state = 'idle'
      AND state_change < current_timestamp - INTERVAL '5' MINUTE;

Trong các phiên bản cũ hơn, bạn cần triển khai các lược đồ phức tạp theo dõi thời điểm kết nối không hoạt động. Đừng bận tâm; chỉ cần sử dụng pgbouncer.


4
Tốt, nhưng nó sẽ giết các phụ trợ PgAdmin khác. Sử dụng điều kiện bổ sung application_name = ''
Andrew Selivanov

1
Tôi có thể chạy pg_termina_backend nếu tôi đang sử dụng pgbouncer không?
Henley Chiu

@HenleyChiu Tôi không hiểu tại sao không, mặc dù tôi chưa kiểm tra cụ thể.
Craig Ringer

1
Việc chạy điều này dường như đã giết chết quy trình gửi WAL của tôi
Joseph Persie,

@CraigRinger thậm chí một kết nối psql được coi là kết nối nhàn rỗi. Và tại sao người ta phải đóng kết nối nhàn rỗi ngay từ đầu. Tôi có một đoạn mã đang chạy dài thiết lập kết nối với pg thực hiện một số hoạt động dml và sau đó đợi thông báo qua hàng đợi và sau đó thực hiện một số hoạt động dml khác. thậm chí sau đó kết nối với bưu chính là idle. tại sao tôi phải đóng nó.
Viren

72

Trong PostgreSQL 9.6, có một tùy chọn mới idle_in_transaction_session_timeoutsẽ hoàn thành những gì bạn mô tả. Bạn có thể đặt nó bằng SETlệnh, ví dụ:

SET SESSION idle_in_transaction_session_timeout = '5min';

1
Thật tệ khi phải hỏi một điều quá đơn giản nhưng tôi là thương hiệu mới đối với cơ sở dữ liệu nói chung - Bạn có thể vui lòng cho một ví dụ rất cơ bản về cách sử dụng chức năng này không?
sg

Bất cứ điều gì giống như thế này trong các phiên bản trước của PostgreSQL ??
sdsc81 25/09/17

Không, một cái gì đó giống với các câu trả lời khác là bắt buộc đối với các phiên bản trước.
shosti 25/09/17

Bạn có cần đặt tham số này mỗi khi khởi động lại cơ sở dữ liệu không? Hoặc sau khi bạn đã làm một lần bạn có thể quên? Cảm ơn
freshko 8/1018

5
SET SESSIONchỉ dành cho phiên hiện tại (nó sẽ trở lại mặc định sau khi bạn mở một kết nối mới). Bạn cũng có thể đặt các tham số cấu hình ở cấp độ cơ sở dữ liệu bằng cách sử dụng ví dụ ALTER DATABASE SET idle_in_transaction_session_timeout = '5min', hoặc sử dụng tệp cấu hình (xem postgresql.org/docs/current/static/config-setting.html ).
shosti

22

Trong PostgreSQL 9.1, các kết nối nhàn rỗi với truy vấn sau. Nó đã giúp tôi tránh khỏi tình huống được bảo đảm khi khởi động lại cơ sở dữ liệu. Điều này chủ yếu xảy ra với các kết nối JDBC được mở và không được đóng đúng cách.

SELECT
   pg_terminate_backend(procpid)
FROM
   pg_stat_activity
WHERE
   current_query = '<IDLE>'
AND
   now() - query_start > '00:10:00';

1
pg_termina_backend bắt đầu từ ngày 8.4
Andrew Banks

8

nếu bạn đang sử dụng postgresql 9.6+, thì trong postgresql.conf của bạn, bạn có thể đặt

idle_in_transaction_session_timeout = 30000 (mili giây)


0

Một giải pháp khả thi cho phép bật thời gian chờ phiên cơ sở dữ liệu mà không cần tác vụ được lên lịch bên ngoài là sử dụng phần mở rộng pg_timeout mà tôi đã phát triển.

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.