Başkaları bağlı olabilirken db'yi zorla


103

Bir veritabanını PostgreSQL DB kümesinden kaldırmam gerekiyor. Aktif bağlantılar olsa bile nasıl yapabilirim? -forceTüm bağlantıları ve sonra da DB'yi bırakacak bir bayrağa ihtiyacım var .

Nasıl uygulayabilirim?

dropdbŞu anda kullanıyorum , ancak başka araçlar da mümkün.

Yanıtlar:


154

PostgreSQL * 'de , istemciler bağlıyken bir veritabanını bırakamazsınız.

En azından, dropdbyardımcı programı ile değil - bu sadece DROP DATABASEsunucu sorgusu etrafında basit bir sarıcı .

Oldukça sağlam bir geçici çözüm şöyle:

Sunucunuza ya da başka bir istemciyi kullanarak süper kullanıcı olarak bağlanın psql. Do not bırakın istediğiniz veritabanını kullanır.

psql -h localhost postgres postgres

Şimdi düz veritabanı istemcisini kullanarak, üç basit adım kullanarak veritabanını bırakmaya zorlayabilirsiniz:

  1. Bu veritabanına kimsenin bağlanamadığından emin olun. Aşağıdaki yöntemlerden birini kullanabilirsiniz (ikincisi daha güvenli görünür, ancak süper kullanıcılardan gelen bağlantıları engellemez).

    /* Method 1: update system catalog */
    UPDATE pg_database SET datallowconn = 'false' WHERE datname = 'mydb';
    
    /* Method 2: use ALTER DATABASE. Superusers still can connect!
    ALTER DATABASE mydb CONNECTION LIMIT 0; */
    
  2. Kullanarak bu veritabanına bağlı tüm istemcilerin bağlantısının kesilmesini zorlayın pg_terminate_backend.

    SELECT pg_terminate_backend(pid)
    FROM pg_stat_activity
    WHERE datname = 'mydb';
    
    /* For old versions of PostgreSQL (up to 9.1), change pid to procpid:
    
    SELECT pg_terminate_backend(procpid)
    FROM pg_stat_activity
    WHERE datname = 'mydb'; */
    
  3. Veritabanını bırak.

    DROP DATABASE mydb;

1. Adım , 1. yöntem için süper kullanıcı ayrıcalıkları ve 2. yöntem için veritabanı sahibi ayrıcalıkları gerektirir . Adım 2, süper kullanıcı ayrıcalıkları gerektirir . Adım 3, veritabanı sahibinin ayrıcalığını gerektirir .


* Bu, PostgreSQL'in tüm sürümleri için geçerlidir, sürüm 11'e kadar.



Neyi yanlış yaptım bilmiyorum ama şimdi hedeflediğim veritabanına bile bağlanamıyorum! Ne de "Bakım veritabanı kaldırılamaz" dediği gibi bırakamaz mıyım
Matt Skeldon

@MattSkeldon, bu mesajın ne anlama geldiği hakkında hiçbir fikrim yok. Vanilya PostgreSQL'de template0 & template1 dışındaki herhangi bir veritabanını bırakabilirsiniz. Belki bazı özgür olmayan / ticari sürümleri kullanıyorsunuzdur? Belki de müşteri sorunu sunucu sorunu değildir? Psql denedin mi?
filiprem

Ne yazık ki bir SQL arkaplanından geliyorum, ticari olmayan / ücretsiz statüsü nedeniyle PGSQL kullanılıyor.
Matt Skeldon

Bu benim için uzun süren zombi seanslarının olduğu yerlerde işe yaramıyor. pg_terminate_backend () bu oturumları öldürmez, bu yüzden ne yapacağım konusunda hala biraz takılıyorum: Postgres bir suyum, ancak çalıştığı sunucuya erişimim yok.
Alexander

6

Orada bir kabuk programları ile yapmak için bir yol dropdbve pg_ctl(veya pg_ctlclusterDebian ve türevleri olarak). Ancak @ filiprem'in yöntemi çeşitli nedenlerden dolayı üstündür :

  • Yalnızca kullanıcıları söz konusu veritabanından ayırır.
  • Tüm kümeyi yeniden başlatması gerekmez.
  • Anında yeniden bağlanmaları önler, muhtemelen dropdbkomutu bozar .

Alıntı yapıyorum man pg_ctlcluster:

--forceSeçeneği ile tüm aktif işlemleri geri alır, istemcileri derhal keser ve böylece temiz bir şekilde kapanır "hızlı" modu kullanılır. Bu işe yaramazsa, kümeyi tutarsız bir durumda bırakabilecek ve böylece bir sonraki başlangıçta kurtarma çalışmasına yol açabilecek olan "acil" modda kapatma işlemi tekrar denenir. Eğer bu hala işe yaramazsa, postmaster işlemi öldürülür. Sunucu çalışmıyorsa 2, diğer hata durumlarında 1 ile başarı ile 0 ile çıkar. Bu mod yalnızca makine kapanmak üzereyken kullanılmalıdır.

pg_ctlcluster 9.1 main restart --force

veya

pg_ctl restart -D datadir -m fast

veya

pg_ctl restart -D datadir -m immediate

hemen ardından:

dropdb mydb

Muhtemelen derhal arka arkaya bir senaryoda.


4
Sadece postgres örneğini başladığından bu idealden daha az değildir, ancak çalışması garanti edilmez. Bir istemcinin sunucuyu yeniden başlattığınız zamana bağlanıp dropdb'yi yeniden çalıştırmayı denemesi mümkündür. @filiprem'in yukarıdaki cevabı, bağlantıyı kesmeden önce veritabanına olan tüm bağlantıları devre dışı bırakır ve diğer veritabanlarını yukarıda tutar.
Jim Mitchener

6

@ Filiprem'in cevabını benim davamda kullanmak ve basitleştirmek:

-- Connecting to the current user localhost's postgres instance
psql

-- Making sure the database exists
SELECT * from pg_database where datname = 'my_database_name'

-- Disallow new connections
UPDATE pg_database SET datallowconn = 'false' WHERE datname = 'my_database_name';
ALTER DATABASE my_database_name CONNECTION LIMIT 1;

-- Terminate existing connections
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'my_database_name';

-- Drop database
DROP DATABASE my_database_name

0

Bir veritabanı seçilmemiş bağlantıların sizi varsayılan olarak oluşturmanızı istediğiniz DB'ye koyduğu RDS gibi bir şeydeyseniz, bu açık değişkeni kendiniz için en son açık bağlantı haline getirebilirsiniz.

 DROP DATABASE IF EXISTS temporary_db_that_shouldnt_exist; 

 CREATE DATABASE temporary_db_that_shouldnt_exist with OWNER your_user; 

 \connect temporary_db_that_shouldnt_exist 
 SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = 'the_db_you_want_removed'; 


 DROP DATABASE IF EXISTS the_db_you_want_removed; 
 -- 
 -- Name: the_db_you_want_removed; Type: DATABASE; Schema: -; Owner: your_user 
 -- 

 CREATE DATABASE savings_champion WITH TEMPLATE = template0 ENCODING = 'UTF8' LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8'; 


 ALTER DATABASE the_db_you_want_removed OWNER TO your_user; 

 \connect the_db_you_want_removed 

 DROP DATABASE IF EXISTS temporary_db_that_shouldnt_exist;
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.