Heroku Postgres - asılı sorguyu sonlandır (işlemde boşta)


99

Heroku'yu Crane Postgres seçeneğiyle kullanıyorum ve yerel makinem çöktüğünde yerel makinemden veritabanında bir sorgu çalıştırıyordum. Eğer koşarsam

select * from pg_stat_activity

girişlerden biri var

<IDLE> in transaction

current_query_text sütununda.

Sonuç olarak, sonlandırılan sorgu tarafından yazılan tabloyu bırakamıyorum. Pg_cancel_backend (N) kullanmayı denedim ve True döndürüyor ama hiçbir şey olmuyor.

Masayı bırakabilmek için bu işlemi nasıl sonlandırabilirim?


1
Belki de soru, "postgres sunucusuna kök erişimi veya veritabanına süper kullanıcı erişimi olmadığında kendi sorgumu nasıl sonlandırırım" şeklinde yeniden ifade edilmelidir. Gerçekten çok iyi bir soru gibi görünüyor ... ve cevabını bilmiyorum.
tobixen

Yanıtlar:


138

Bu genel bir Postgres cevabıdır ve heroku'ya özgü değildir


(Bu sorunun basit-aptalca cevabı ... sadece postgresql'i yeniden başlatmak olabilir. Bunun istenmediğini veya bir seçenek olmadığını varsayarsak ...)

Bu sql'yi çalıştırarak PID'yi bulun:

SELECT pid , query, * from pg_stat_activity
  WHERE state != 'idle' ORDER BY xact_start;

(Sorgunun postgres sürümüne bağlı olarak onarılması gerekebilir - sonunda, pg_stat_activity'den * öğesini seçin). Pid'i ilk (sol) sütunda bulacaksınız ve ilk (üst) satır büyük olasılıkla sonlandırmak istediğiniz sorgu olacaktır. Aşağıdaki pid'in 1234 olduğunu varsayacağım.

Size ait olduğu veya süper kullanıcı erişiminiz olduğu sürece SQL aracılığıyla bir sorguyu iptal edebilirsiniz (yani kabuk erişimi olmadan):

select pg_cancel_backend(1234);

Bu, 1234 sorgusunu iptal etmek için "dostça" bir istek ve biraz şansla bir süre sonra kaybolacak. Sonuç olarak, bu daha etkilidir:

select pg_terminate_backend(1234);

Kabuk erişiminiz ve kök veya postgres izinleriniz varsa, bunu kabuktan da yapabilirsiniz. "İptal etmek" için şunları yapabilirsiniz:

kill -INT 1234

ve "sonlandırmak" için basitçe:

kill 1234

YAPMA:

kill -9 1234

... bu genellikle tüm postgres sunucusunun alevler içinde kalmasıyla sonuçlanır, o zaman postgres'i yeniden başlatabilirsiniz. Postgres oldukça sağlamdır, bu nedenle veriler bozulmaz, ancak her durumda "kill -9" kullanılmamasını öneririm :-)


Uzun süreli "işlemde boşta kalma", genellikle işlemin bir "kesinleştirme" veya "geri alma" ile sonlandırılmadığı anlamına gelir; bu, uygulamanın hatalı olduğu veya işlem veritabanları ile çalışmak üzere uygun şekilde tasarlanmadığı anlamına gelir. Büyük performans sorunlarına da yol açabileceğinden, uzun süreli "boşta kalma" işleminden kaçınılmalıdır.


Pg_cancel_backend'i boşuna denedim. Kabuk erişimim yok ve süper kullanıcı değilim, bu yüzden pg_terminate_backend kullanarak SIGKILL gönderemiyorum
alan

Hangi postgres sürümünü kullanıyorsunuz? (ipucu:) select version(). Kullanırken herhangi bir hata mesajı alıyor pg_cancel_backendmusunuz?
tobixen

Pg_cancel_backend'i kendim kullanmak için bir girişimde bulundum, bu yüzden "diğer sunucu işlemlerini işaret etmek için süper kullanıcı olmalı" hata mesajı aldım ... bu, görünüşe göre sunucuda kök erişimine veya bazı postgres süper kullanıcısı (yani postgres kullanıcısı) aracılığıyla db erişimine ihtiyacınız olacağı anlamına gelir ) kendi sorgunuzu sonlandırmak için. Bu biraz berbat görünüyor :-(
tobixen

1
işlemlerin pg_cancel_backend tarafından iptal edildiği ortaya çıktı, ancak sorgular bir süredir pg_stat_activity'de gösteriliyor
alan

Belki de Heroku'ya özgüdür. Görebildiğim kadarıyla, sıradan postgres altında sıkışmış bir süreci öldürmek için gerçekten süper kullanıcı olmak gerekiyor (sayfa 8.4'te "select pg_sleep (3600)" ile test ediyorum ve "HATA: sinyal için süper kullanıcı olmalı diğer sunucu işlemleri "). Yine de "işlemde boşta kalma" tam olarak aynı değildir.
tobixen

36

Bunu dene:

select pg_terminate_backend(pid int)

Bununla ilgili daha fazla bilgiyi burada bulabilirsiniz . Bu, bu sorunun sistem tarafından öldürülmekten daha 'daha temiz' bir çözümü olmalıdır.


Lütfen cevabınıza pidinizi nasıl alacağınızı ekleyin
mountainclimber

19

heroku-pg-extrasEklentiyi kurabilir ve PID'yi almak için aşağıdaki komutu çalıştırabilirsiniz:

heroku pg:locks --app <your-app>

O zaman yap:

heroku pg:kill <pid> --app <your-app> 

NOT : --forceseçenek o sorgu için tüm bağlantı bırakır konu pg_terminate_backend için kullanılabilir.

Eğer heroku pg:locksdeğil liste şey yapar deneyin heroku pg:ps.

Daha fazla bilgi için bakın:
https://devcenter.heroku.com/articles/heroku-postgresql#pg-ps-pg-kill-pg-killall


Teşekkür ederim. Yine de işlemi / PID'yi sonlandıramıyorum ... bilgisayarım içe aktarma sırasında bir donanım dondu ve PID'yi sonlandıramıyorum. :(
dimitarvp

-3

Bunu tek bir sorguda elde etmek için aşağıdakileri kullanabiliriz:

SELECT pg_cancel_backend(pid), pg_terminate_backend(pid) FROM pg_stat_activity WHERE state != 'idle';

bu çalışan tüm sorguları kapatırsa, postgres yeniden başlatılabilir. xact_start ve limit 1 ile sipariş verdim ve kabul edebilirim ... ama yine de, körü körüne öldürmeden önce listeye bakmayı tercih ederim.
tobixen

Peki buna ne dersin? SELECT pid, pg_cancel_backend(pid) FROM pg_stat_activity WHERE state != 'idle' AND (now() - query_start) > interval '5 minutes';
AFN
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.