2012-09-12 37 views
26

Một số máy khách kết nối với cơ sở dữ liệu postgresql của chúng tôi nhưng để các kết nối được mở. Có thể yêu cầu Postgresql đóng các kết nối đó sau một lượng không hoạt động nhất định không?Làm cách nào để tự động đóng các kết nối nhàn rỗi trong PostgreSQL?

TL; DR

NẾU bạn đang sử dụng một phiên bản PostgreSQL> = 9.2
THEN sử dụng the solution I came up with

NẾU bạn không muốn viết bất kỳ mã
THEN sử dụng arqnid's solution

+2

Bạn có thể sử dụng một công việc định kỳ để xem xét khi kết nối lần cuối hoạt động (xem 'pg_stat_activity') và sử dụng' pg_terminate_backend' để giết người cũ. Dễ dàng thể hiện trong một truy vấn đơn giản. Tôi không chắc liệu 'pg_terminate_backend' có sẵn trong phiên bản 8.3 hay không. –

Trả lời

27

Đối với những người quan tâm, đây là giải pháp tôi đã đưa ra, lấy cảm hứng từ Craig Ringer 's bình luận:

(...) sử dụng một công việc định kỳ để xem xét khi kết nối lần cuối tích cực (xem pg_stat_activity) và sử dụng pg_terminate_backend để giết những cái cũ (...)

Các giải pháp được lựa chọn đi xuống như thế này:.

  • Đầu tiên, chúng tôi nâng cấp lên Postgresql 9.2.
  • Sau đó, chúng tôi lên lịch một chuỗi để chạy mỗi giây.
  • Khi chuỗi chạy, nó tìm kiếm bất kỳ kết nối không hoạt động cũ nào.
    • Một kết nối được coi không hoạt động nếu trạng thái của nó là một trong haiidle, idle in transaction, idle in transaction (aborted) hoặc disabled.
    • Kết nối được coi là nếu trạng thái cuối cùng của nó đã thay đổi trong hơn 5 phút.
  • Có các chuỗi bổ sung tương tự như trên. Tuy nhiên, những luồng đó kết nối với cơ sở dữ liệu với người dùng khác.
  • Chúng tôi để lại ít nhất một kết nối mở cho bất kỳ ứng dụng nào được kết nối với cơ sở dữ liệu của chúng tôi. (rank() chức năng)

Đây là truy vấn SQL chạy bởi thread:

WITH inactive_connections AS (
    SELECT 
     pid, 
     rank() over (partition by client_addr order by backend_start ASC) as rank 
    FROM 
     pg_stat_activity 
    WHERE 
     -- Exclude the thread owned connection (ie no auto-kill) 
     pid <> pg_backend_pid() 
    AND 
     -- Exclude known applications connections 
     application_name !~ '(?:psql)|(?:pgAdmin.+)' 
    AND 
     -- Include connections to the same database the thread is connected to 
     datname = current_database() 
    AND 
     -- Include connections using the same thread username connection 
     usename = current_user 
    AND 
     -- Include inactive connections only 
     state in ('idle', 'idle in transaction', 'idle in transaction (aborted)', 'disabled') 
    AND 
     -- Include old connections (found with the state_change field) 
     current_timestamp - state_change > interval '5 minutes' 
) 
SELECT 
    pg_terminate_backend(pid) 
FROM 
    inactive_connections 
WHERE 
    rank > 1 -- Leave one connection for each application connected to the database 
+0

Cuối cùng, chúng tôi chuyển sang Postgresql 9.2 để tận dụng lợi thế của 'pg_terminate_backend'. Chúng tôi đã sử dụng cron như job để định kỳ gọi 'pg_terminate_backend'. – Stephan

+0

Bạn có thể đăng một tập lệnh mà bạn sử dụng không? – Andrus

+0

@Andrus Xem cập nhật trong câu trả lời của tôi. – Stephan

10

Kết nối thông qua proxy như PgBouncer sẽ đóng các kết nối sau server_idle_timeout giây.

+0

có thể pg pool II làm tương tự? – wolf97084

+0

@ wolf97084 Xem câu trả lời này: http: // stackoverflow.com/a/30769511/363573 – Stephan

+0

@Stephan Cảm ơn bạn! Tôi sẽ bỏ lỡ câu trả lời nếu bạn không gắn thẻ tôi trong nhận xét. – wolf97084

Các vấn đề liên quan