Boştaki PostgreSQL bağlantıları için bir zaman aşımı var mı?


99
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             

Bir çoğunu görüyorum. Bağlantı sızıntımızı gidermeye çalışıyoruz. Ancak bu arada, bu boş bağlantılar için bir zaman aşımı ayarlamak istiyoruz, belki en fazla 5 dakika.


DB'ye nasıl bağlanıyorsunuz? socketTimeout aradığınız şey olabilir.
Doon

Bu eski Pylons web uygulamasına sahibiz ve SQLAlchemy'yi kullandık, ancak görünüşe göre onu düzgün kullanmadık. Ben hatırlamıyorum Sızıntıyı gidermeye çalışıyoruz. socketTimeoutDokümandan DB ile olan bağlantıyı tamamen bu kadar yakınmış gibi görünüyor. Her boşta kalma durumunu kapatmaya çalışıyorum ve bağlantı kurulur kurulmaz sayaç başlıyor.
user1012451


@ user1012451 "Boşta kalan her birini kapat" dediğinizde - <IDLE> in transactionoturumu çalışır halde bırakarak oturumları sonlandırmak mı istiyorsunuz <IDLE>? Başka bir deyişle, işlemi sonlandırıp oturumu değil? (Olumsuz oy verildi: net olmayan soru)
Craig Ringer

@CraigRinger bir süre sonra maksimum müşteri bağlantısına ulaşıyoruz. Bunu çözmek için, postgresql'i de yeniden başlatmaya zorlayan web uygulamasını yeniden başlatmalıyız. Bu her bağlantıyı yok eder. Bunları idlesonsuza dek gördüğümüzde, her bağlantı / oturum için bir zaman aşımı belirleyip ayarlayamayacağımızı soruyoruz (dürüst olmak gerekirse doğru terminolojiyi bilmiyorum, üzgünüm). Normal bir web uygulaması için bir işlem 5 dakika
sürüyorsa bir

Yanıtlar:


120

Havuza alınan bağlantıları kapatamadığı için uygulamanızda bir bağlantı sızıntısı var gibi görünüyor . Sadece oturumlarla ilgili değil , genel olarak çok fazla bağlantıyla ilgili sorunlar yaşıyorsunuz .<idle> in transaction

Bağlantıları kesmek bunun için doğru cevap değildir, ancak bu bir OK-ish geçici çözümdür.

Bir PostgreSQL veritabanından diğer tüm bağlantıları başlatmak için PostgreSQL'i yeniden başlatmak yerine, bkz: Diğer tüm kullanıcıları bir postgres veritabanından nasıl ayırabilirim? ve Etkin bağlantılar varsa bir PostgreSQL veritabanı nasıl bırakılır? . İkincisi, daha iyi bir sorgu gösterir.

@Doon'un önerdiği gibi zaman aşımlarını ayarlamak için PostgreSQL'de boşta kalan bağlantılar otomatik olarak nasıl kapatılır? , bu da PostgreSQL için proxy kullanmak ve boş bağlantıları yönetmek için PgBouncer'ı kullanmanızı önerir. Bağlantıları yine de sızdıran hatalı bir uygulamanız varsa bu çok iyi bir fikirdir; Ben çok güçlü bir şekilde pgBouncer yapılandırılması önerilir.

Bir TCP canlı tutma buradaki işi yapmaz, çünkü uygulama hala bağlı ve canlıdır, olmamalı.

PostgreSQL 9.2 ve üzeri sürümlerde, boşta bir bağlantı düzenleyici uygulamak için yeni state_changezaman damgası sütununu ve statealanını pg_stat_activitykullanabilirsiniz. Bir cron işi böyle bir şey çalıştırsın:

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;

Eski sürümlerde, bağlantının ne zaman boşta kaldığını takip eden karmaşık şemalar uygulamanız gerekir. Rahatsız etmeyin; sadece pgbouncer kullanın.


4
İyi, ancak diğer PgAdmin arka uçlarını öldürecek. Ek koşul application_name = '' kullanın
Andrew Selivanov

1
Pgbouncer kullanıyorsam pg_terminate_backend çalıştırabilir miyim?
Henley Chiu

@HenleyChiu Özel olarak kontrol etmemiş olsam da neden olmadığını anlamıyorum.
Craig Ringer

1
Bunu çalıştırmak WAL gönderme sürecimi öldürmüş gibi görünüyor
Joseph Persie

@CraigRinger bir psql bağlantısı bile boşta bağlantı olarak kabul edilir. Ve neden ilk etapta boştaki bağlantıyı kapatmak gerekiyor? Pg ile bağlantı kuran uzun süredir çalışan bir kodum var, bazı dml işlemleri gerçekleştiriyor ve ardından mesajı kuyruğun üzerinde bekle ve ardından biraz daha dml işlemi gerçekleştiriyor. o zaman bile postalarla olan bağlantı idle. neden kapatmalıyım
Viren

73

PostgreSQL 9.6'da, idle_in_transaction_session_timeouttanımladığınız şeyi başarması gereken yeni bir seçenek var. Bunu şu SETkomutu kullanarak ayarlayabilirsiniz , örneğin:

SET SESSION idle_in_transaction_session_timeout = '5min';

1
Bu kadar basit bir şey sormak berbat bir şey ama genel olarak veritabanlarında yeniyim - Lütfen bu işlevi nasıl kullanacağınıza dair çok basit bir örnek verebilir misiniz?
sg

PostgreSQL'in önceki sürümlerinde buna benzer herhangi bir şey?
sdsc81

Hayır, önceki versiyonlar için diğer cevaplara benzer bir şey gereklidir.
shosti

Veritabanının her yeniden başlatılmasında bu parametreyi ayarlamanız gerekiyor mu? Ya da bir kez yaptıktan sonra unutabilir misin? Teşekkürler
fresko

5
SET SESSIONsadece mevcut oturum içindir (yeni bir bağlantı açtığınızda varsayılana geri dönecektir). Yapılandırma parametrelerini, örneğin ALTER DATABASE SET idle_in_transaction_session_timeout = '5min', veya yapılandırma dosyalarını kullanarak bir veritabanı düzeyinde de ayarlayabilirsiniz (bkz. Postgresql.org/docs/current/static/config-setting.html ).
shosti

22

PostgreSQL 9.1'de, aşağıdaki sorgu ile boşta bağlantılar. Veritabanını yeniden başlatmamı sağlayan durumu önlememe yardımcı oldu. Bu, çoğunlukla açık ve düzgün kapatılmamış JDBC bağlantıları ile olur.

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

1
pg_terminate_backend 8.4'ten beri içinde
Andrew Banks

8

postgresql 9.6+ kullanıyorsanız, postgresql.conf dosyanızda şu ayarları yapabilirsiniz:

idle_in_transaction_session_timeout = 30000 (msn)


0

Harici bir zamanlanmış görev olmadan veritabanı oturumu zaman aşımını etkinleştirmeye izin veren olası bir çözüm, geliştirdiğim pg_timeout uzantısını kullanmaktır .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.