Etkin bağlantılar varsa bir PostgreSQL veritabanı nasıl bırakılır?


648

Bir PostgreSQL veritabanı bırakacak bir komut dosyası yazmak gerekiyor. Çok fazla bağlantı olabilir, ancak komut dosyası bunu görmezden gelmelidir.

DROP DATABASE db_nameAçık bağlantılar olduğunda standart sorgu çalışmaz.

Sorunu nasıl çözebilirim?


1
Hangi PostgreSQL sürümünü kullanıyorsunuz?
Kuberchaun

1
Sorun: Veritabanına bağlı oturumları öldürebilirken, veritabanını bırakamayacağınız kadar hızlı bir şekilde yeniden bağlanabilirler. Mutlu bir şekilde bu yazı yeni bağlantıların nasıl kilitleneceğini gösterir, böylece mevcut bağlantıları öldürebilir ve veritabanını plana göre düşürebilirsiniz
Max Murphy

1
Bu cevabı çok yardımcı olmak için dba.stackexchange'te buldum dba.stackexchange.com/a/11895/163539 - özlü ama yeterince açıklayıcı.
hlongmore

Yanıtlar:


1093

Bu sizinki dışında mevcut bağlantıları bırakacaktır:

pg_stat_activityÖldürmek istediğiniz pid değerlerini sorgulayın ve alın, sonra SELECT pg_terminate_backend(pid int)onlara verin.

PostgreSQL 9.2 ve üstü:

SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB' -- ← change this to your DB
  AND pid <> pg_backend_pid();

PostgreSQL 9.1 ve altı:

SELECT pg_terminate_backend(pg_stat_activity.procpid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB' -- ← change this to your DB
  AND procpid <> pg_backend_pid();

Herkesin bağlantısını kestikten sonra bağlantıyı kesip DROP DATABASE komutunu başka bir veritabanından, yani bırakmaya çalıştığınız bir bağlantıdan çıkarmanız gerekir.

procpidSütunun yeniden adlandırılmasını not edin pid. Bu posta listesi konusuna bakın .


11
Ve elbette, bunu 'TARGET_DB' bağlantısı olmayan bir db bağlantısından yaptığınızdan emin olun, aksi takdirde 'ERROR' alırsınız. Bir 'postgres' bağlantısı iyi çalışıyor.
Rob

3
Aslında istemcilerin birer birer bağlantısını keser ve istemciniz listenin ortasındaysa da bağlantısı kesilir. Sonuç olarak, bazı bağlantılar hayatta kalacaktır. Yani, doğru cevap Craig Ringer tarafındandır (aşağıya bakınız). SEÇ pg_terminate_backend (pg_stat_activity.pid) FROM pg_stat_activity NEREDE datname = current_database () AND pg_stat_activity.pid <> pg_backend_pid ();
Andrew Selivanov

1
Geçerli işlemleri bitirdikten sonra söz konusu tabloları bıraktıktan sonra bağlantıları nasıl kesebilirim?
paulkon

5
Benim durumumda müşteriler hızlı bir şekilde yeniden bağlanacaktı, bu yüzden ; drop database TARGET_DB;db'nin işler yeniden denemeye başladığı zaman gittiğinden emin olmak için benim durumumda iyi çalıştı.
Mat Schaffer

1
Bir para bile ödeyecektim dropdb --force.
Torsten Bronger

125

PostgreSQL 9.2 ve üzeri sürümlerde, oturumunuz dışındaki her şeyin bağlı olduğunuz veritabanından bağlantısını kesmek için:

SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE datname = current_database()
  AND pid <> pg_backend_pid();

Eski sürümlerde aynı, sadece bir değişiklik pidiçin procpid. Farklı bir veritabanının current_database()bağlantısını kesmek için, kullanıcıların bağlantısını kesmek istediğiniz veritabanının adını değiştirin .

Sen isteyebilirsiniz , kullanıcıları ayırmadan önce veritabanının kullanıcılardan hakkı aksi kullanıcılar sadece yeniden bağlanma devam edecektir ve siz DB düşmesi şans asla. Bkz Bu yorumu ve o ilişkilendirilmiş soru veritabanından ben ayırmak nasıl diğer tüm kullanıcılar .REVOKECONNECT

Sadece boştaki kullanıcıların bağlantısını kesmek istiyorsanız, bu soruya bakın .


3
SEÇ pg_terminate_backend (pg_stat_activity.pid) FROM pg_stat_activity NEREDE datname = current_database () AND pg_stat_activity.pid <> pg_backend_pid ();
Andrew Selivanov

26

pg_terminate_backend(int)İşlevi kullanarak veritabanını bırakmadan önce tüm bağlantıları öldürebilirsiniz .

Sistem görünümünü kullanarak tüm çalışan arka uçları alabilirsiniz pg_stat_activity

Tam olarak emin değilim, ancak aşağıdakiler muhtemelen tüm oturumları öldürür:

select pg_terminate_backend(procpid)
from pg_stat_activity
where datname = 'doomed_database'

Tabii ki kendinizi bu veritabanına bağlı olmayabilir


19

Postgresql sürümünüze bağlı olarak pg_stat_activity, bırakılan kullanıcılardan etkin bağlantıları atlamayı sağlayan bir hata ile karşılaşabilirsiniz . Bu bağlantılar pgAdminIII içinde de gösterilmez.

Otomatik sınama (kullanıcı da oluşturduğunuz) yapıyorsanız bu olası bir senaryo olabilir.

Bu durumda aşağıdaki gibi sorgulara geri dönmeniz gerekir:

 SELECT pg_terminate_backend(procpid) 
 FROM pg_stat_get_activity(NULL::integer) 
 WHERE datid=(SELECT oid from pg_database where datname = 'your_database');

NOT: 9.2+ size değişiklik olur procpidiçin pid.


1
Bu aradığım şeydi ama (9.2 ve ötesini varsayarak) pg_stat_activity referans kaldırmak ve pid için procpid değiştirmek zorunda.
MDR

2
Değiştirdikten sonra procpidhiç pid9.3 bu pasajı eserleri.
jb.

pg_stat_activity'yi çıkarmadan bile? 9.2
MDR

TAMAM. Şimdi anlıyorum, bu bir yazım hatasıydı. Teşekkürler!
jb.

2
9.3 ve üstü SELECT pg_terminate_backend (pid) FROM pg_stat_get_activity (NULL :: integer) WHERE datid = (datname = 'veritabanınız' da pg_database'den SELECT oid);
Shawn Vader

17

Postgres 9.2'nin şimdi procpid yerine sütun pid'i çağırdığını fark ettim.

Kabuktan çağırma eğilimindeyim:

#!/usr/bin/env bash
# kill all connections to the postgres server
if [ -n "$1" ] ; then
  where="where pg_stat_activity.datname = '$1'"
  echo "killing all connections to database '$1'"
else
  echo "killing all connections to database"
fi

cat <<-EOF | psql -U postgres -d postgres 
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
${where}
EOF

Umarım faydalıdır. Sql için @JustBob'a teşekkürler.


15

Bağlı istemcilerin bağlantısını kesmek için Ubuntu'daki hizmeti yeniden başlatıyorum.

sudo service postgresql stop
sudo service postgresql start

psql
DROP DATABASE DB_NAME;

10

Linux komut isteminde, önce bu sudo /etc/init.d/postgresql restart komutunu yazarak çalışan tüm postgresql işlemlerini durdururum

diğer postgresql işlemlerinin hala çalışıp çalışmadığını kontrol etmek için bg komutunu yazın

sonra veritabanını bırakmak için dropdb dbname

sudo /etc/init.d/postgresql restart
bg
dropdb dbname

Bu benim için linux komut isteminde çalışıyor


6
Çok sayıda veritabanınız varsa ve yalnızca tek bir DB için bağlantıları bırakmak istiyorsanız bu iyi değildir. Bu, tüm bağlantıları öldürür. Biraz "kızak çekiç-y".
Nick

2
@Nick true ama tüm bağlantıları yeniden başlatıp tamamen durdurduğumuzu
hatırla

10

PostgreSQL 9.2 ve üstü:

SELECT pg_terminate_backend(pid)FROM pg_stat_activity WHERE datname = 'YOUR_DATABASE_NAME_HERE'


Bu aktif bağlantıyı da sonlandırmayacak mı?
Cocowalla

8

İşte benim hack ... = D

# Make sure no one can connect to this database except you!
sudo -u postgres /usr/pgsql-9.4/bin/psql -c "UPDATE pg_database SET datallowconn=false WHERE datname='<DATABASE_NAME>';"

# Drop all existing connections except for yours!
sudo -u postgres /usr/pgsql-9.4/bin/psql -c "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '<DATABASE_NAME>' AND pid <> pg_backend_pid();"

# Drop database! =D
sudo -u postgres /usr/pgsql-9.4/bin/psql -c "DROP DATABASE <DATABASE_NAME>;"

Bu cevabı, yeni bağlantıları engellemek için bir komut (yukarıda) içerdiğinden ve komutla yapılan herhangi bir girişimden dolayı ...

REVOKE CONNECT ON DATABASE <DATABASE_NAME> FROM PUBLIC, <USERS_ETC>;

... yeni bağlantıları engellemek için çalışmıyor!

@Araqnid @GoatWalker sayesinde! = D

https://stackoverflow.com/a/3185413/3223785


5

Yaklaşan PostgreSQL 13 FORCEseçeneği tanıtılacak .

DROP VERİTABANI

DROP DATABASE bir veritabanını bırakır ... Ayrıca, hedef veritabanına başka biri bağlıysa , aşağıda açıklanan FORCE seçeneğini kullanmadığınız sürece bu komut başarısız olur .

GÜÇ

Hedef veritabanına var olan tüm bağlantıları sonlandırmayı deneyin. Hedef veritabanında hazırlanmış işlemler, etkin mantıksal çoğaltma yuvaları veya abonelikler mevcutsa sonlandırılmaz.

DROP DATABASE db_name WITH (FORCE);

0

Benim durumumda, aktif yönetici bağlantım dahil tüm bağlantıları bırakmak için bir komut yürütmek zorunda kaldım

SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE datname = current_database()

tüm bağlantıları sonlandırdı ve bana ölümcül bir '' hata '' mesajı gösterdi:

FATAL: terminating connection due to administrator command SQL state: 57P01

Bundan sonra veritabanını bırakmak mümkün oldu


0

Benim için hiçbir şey işe yaramadı, pgAdmin4 kullanarak oturum açtım ve Gösterge Tablosunda pgAdmin4 dışındaki tüm bağlantıların bağlantısını kestim ve sonra veritabanına ve özelliklere sağa yatarak yeniden adlandırabiliyordum ve yeni bir ad yazabildim.

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.