Postgresql - DB'ye bazı otomatik bağlantılar nedeniyle veritabanı bırakılamıyor


163

Ne zaman veritabanı bırakmaya çalıştığınızda olsun:

ERROR:  database "pilot" is being accessed by other users
DETAIL:  There is 1 other session using the database.

Kullandığımda:

SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB';

Ben o DB bağlantı sonlandırıldı, ama bundan sonra veritabanı bırakmaya çalışırsanız bir şekilde birileri otomatik olarak bu veritabanına bağlanır ve bu hatayı verir. Bunu ne yapabilir? Bu veritabanını benden kimse kullanmıyor.

Yanıtlar:


198

Gelecekteki bağlantıları engelleyebilirsiniz:

REVOKE CONNECT ON DATABASE thedb FROM public;

(ve muhtemelen diğer kullanıcılar / rolleri; bakınız \l+içinde psql)

Daha sonra bu db'ye kendi bağlantılarınız dışındaki tüm bağlantıları sonlandırabilirsiniz:

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

Eski sürümlerde pidçağrıldı, procpidbu yüzden bununla uğraşmanız gerekecek.

CONNECTHakları iptal ettiğiniz için, otomatik olarak bağlanmaya çalışan her şey artık bunu yapamaz.

Artık DB'yi bırakabileceksiniz.

Normal işlemler için süper kullanıcı bağlantıları kullanıyorsanız bu işe yaramaz, ancak bunu yapıyorsanız önce bu sorunu düzeltmeniz gerekir.


Veritabanını bıraktıktan sonra, veritabanını yeniden oluşturursanız, erişimi geri yüklemek için aşağıdaki komutu yürütebilirsiniz

GRANT CONNECT ON DATABASE thedb TO public;

19
Daha sonra aynı ada sahip başka bir veritabanını içe aktarırsanız, herkese açık GRANT CONNECT ON DATABASE thedb TO public;
olana

156

Ne zaman veritabanı bırakmaya çalıştığınızda olsun:

ERROR:  database "pilot" is being accessed by other users
DETAIL:  There is 1 other session using the database.

Önce iptal etmelisin

REVOKE CONNECT ON DATABASE TARGET_DB FROM public;

Sonra kullan:

SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB';

Kesinlikle işe yarayacak.


5
Bu benim için yaptı. Teşekkürler
rpivovar

1
Bulun! Teşekkür ederim! 🎉
slajma

1
Mükemmel çalıştı. Teşekkür ederim.
Mustafa Magdi

34

Bu sorun için bir çözüm buldum terminalde bu komutu çalıştırmayı deneyin

ps -ef | grep postgres

işlemi bu komutla öldür

sudo kill -9 PID

Hayır, bu çok zor bir kod, erişilen başka veritabanlarınız olduğu için pg işlemini başlatamazsanız ne olacak?
Vladimir Stazhilov

2
@VladimirStazhilov Bu veritabanının veritabanı adını ve pid'ini gösterecektir. birisi sadece belirli bir veritabanı belirli pid kill seçebilirsiniz.
Dinesh Pallapa

29

Bağlantının ne olduğunu, nereden geldiğini kontrol etmeniz yeterlidir. Tüm bunları şurada görebilirsiniz:

select * from pg_stat_activity where datname = 'TARGET_DB';

Belki senin bağlantın mı?


4
sudo kill -9 PID sonucu gördükten sonra terminalde
Dan Rey Oquindo

25

Başka bir kullanıcının veritabanına eriştiği anlamına gelir. PostgreSQL'i yeniden başlatmanız yeterlidir. Bu komut hile yapacak

root@kalilinux:~#sudo service postgresql restart

Ardından veritabanını bırakmayı deneyin:

postgres=# drop database test_database;

Bu hile yapacak.


11

pgAdmin 4 UI kullanarak çözüm

Öncelikle, aşağıdakileri yapmadıysanız gösterge tablosunda gösteri etkinliğini etkinleştirin:

File > Preferences > Dashboards > Display > Show Activity > true

Şimdi db'yi kullanarak tüm işlemleri devre dışı bırakın:

  1. DB adını tıklayın
  2. Gösterge Tablosu> Oturumlar'ı tıklayın
  3. Yenile simgesini tıklayın
  4. İşlemleri sonlandırmak için her bir işlemin yanındaki sil (x) simgesini tıklayın

Şimdi db silebilir.


Bu iyi çalışıyor - Visual C ++ build 1914, 64-bit (Windows) tarafından derlenen PgAdmin 4.5 ve PostgreSQL 11.2 ile test ettim.
vab2048

2
Bu bence en iyi çözüm. Bu gerçekten iyi çalışıyor!
Lahiru

10

Makinenizdeki diğer hizmetler üzerinde potansiyel bir etkisi yoksa, service postgresql restart


8

Çözüm:
1. Pg sunucusunu kapatın 2. Tüm etkin bağlantının bağlantısını kesecektir 3. Pg Sunucusunu yeniden başlatın 4. Komutunuzu deneyin
resim açıklamasını buraya girin




Mac için Postgress.app ile bu da benim için çalıştı. Bu durumda sunucuyu durdurur / başlatırsınız
Juan José Ramírez


3

Benim durumumda, AWS Redshift (Postgres'e dayanarak) kullanıyorum. Ve DB başka hiçbir bağlantı var gibi görünüyor, ama aynı hatayı alıyorum.

ERROR:  database "XYZ" is being accessed by other users

Benim durumumda, veritabanı kümesi hala veritabanında bazı işlemler yapıyor gibi görünüyor ve başka harici / kullanıcı bağlantıları olmasa da, veritabanı hala dahili olarak kullanılıyor. Bunu aşağıdakileri çalıştırarak buldum:

SELECT * FROM stv_sessions;

Yani benim hack kod içinde bir döngü yazmak, benim veritabanı adı ile satır aramak oldu. (tabii ki döngü sonsuz değildir ve uykulu bir döngüdür)

SELECT * FROM stv_sessions where db_name = 'XYZ';

Satırlar bulunursa, her bir PID'yi tek tek silmeye devam edin.

SELECT pg_terminate_backend(PUT_PID_HERE);

Hiçbir satır bulunmazsa, veritabanını bırakmaya devam edin

DROP DATABASE XYZ;

Not: Benim durumumda, Java birim / sistem testleri yazıyorum, bunun kabul edilebilir olduğu düşünülebilir. Bu, üretim kodu için kabul edilemez.


İşte Java'da tam bir hack (test / yardımcı program sınıflarımı yoksay).

  int i = 0;
  while (i < 10) {
    try {
      i++;
      logStandardOut("First try to delete session PIDs, before dropping the DB");
      String getSessionPIDs = String.format("SELECT stv_sessions.process, stv_sessions.* FROM stv_sessions where db_name = '%s'", dbNameToReset);
      ResultSet resultSet = databaseConnection.execQuery(getSessionPIDs);
      while (resultSet.next()) {
        int sessionPID = resultSet.getInt(1);
        logStandardOut("killPID: %s", sessionPID);
        String killSessionPID = String.format("select pg_terminate_backend(%s)", sessionPID);
        try {
          databaseConnection.execQuery(killSessionPID);
        } catch (DatabaseException dbEx) {
          //This is most commonly when a session PID is transient, where it ended between my query and kill lines
          logStandardOut("Ignore it, you did your best: %s, %s", dbEx.getMessage(), dbEx.getCause());
        }
      }

      //Drop the DB now
      String dropDbSQL = String.format("DROP DATABASE %s", dbNameToReset);
      logStandardOut(dropDbSQL);
      databaseConnection.execStatement(dropDbSQL);
      break;
    } catch (MissingDatabaseException ex) {
      //ignore, if the DB was not there (to be dropped)
      logStandardOut(ex.getMessage());
      break;
    } catch (Exception ex) {
      logStandardOut("Something went wrong, sleeping for a bit: %s, %s", ex.getMessage(), ex.getCause());
      sleepMilliSec(1000);
    }
  }

2

Bence kağıtta çalışan bazı boş sorgular var.

  1. Önce çalışan sorguları göstermeyi deneyin
SELECT pid, age(clock_timestamp(), query_start), usename, query 
FROM pg_stat_activity 
WHERE query != '<IDLE>' AND query NOT ILIKE '%pg_stat_activity%' 
ORDER BY query_start desc;
  1. boşta sorguyu öldür (söz konusu veritabanına başvuruda bulunup bulunmadıklarını kontrol edin veya seçilen sonuçlardan pid'i kullanarak tümünü veya belirli bir kişiyi öldürebilir misiniz)

SEÇ pg_terminate_backend (procpid);

Not: Seçili bir sorguyu öldürmek kötü bir etki yaratmaz


2

REVOKE CONNECTdb sahibinden veya süper kullanıcıdan gelen bağlantıları engellemez. Kimsenin db'yi bağlamasını istemiyorsanız, follow komutu yararlı olabilir.

alter database pilot allow_connections = off;

Sonra kullan:

SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'pilot';

1
Teşekkürler ... REVOKE CONNECT senaryomda yeterli değildi.
volpato

1

En çok oylanan iki yanıtı diğer durumlarda yararlı bulurken, bugün, sorunu çözmenin en basit yolu PyCharm'ın bir oturumu açık tutuyor olabileceğini ve StopPyCharm'ı tıklarsam bu yardımcı olabilir. PgAdmin4 tarayıcıda açıkken, bunu yaptım ve hemen hemen Veritabanı oturumları istatistiklerinin 0'a düştüğünü gördüm, bu noktada veritabanını bırakabildim.


"PyCharm bir oturumu açık tutuyor olabilir"? Nasıl? PyCharm'ın terminalinde (peewee ile ön uç Python, arka uç Postgres) birim testleri çalıştırıyorum, yani "Durdur" düğmesi gri renkte ve yine de bu hataları
koruyorum

@LaryxDecidua Benim durumumda, db kullanılan PyCharm çalışan bir hizmet örneği olması gerektiğine inanıyorum. PyCharm'dan çıkarsanız, örnek sayısı 0'a düşer ve db'yi bırakmanıza izin verir mi? Öyleyse, hala bağlı olan bir şey (veritabanı gezgini, SQL sorgusu, başka bir şey) olmalıdır.
hlongmore

1

MacOS komutunu kullanarak postgresql veritabanını konsoldan yeniden başlatmayı deneyin:

brew services restart postgresql

-1

Terminalde şu komutu deneyin:

ps -ef | grep postgres

şöyle göreceksiniz:

501 1445 3645 0 12:05 AM 0: 00.03 postgres: sasha dbname [yerel] boşta

Üçüncü sayı (3645) PID'dir.

Bunu silebilirsiniz

sudo kill -9 3645

Bundan sonra PostgreSQL bağlantınızı başlatın.

Manuel olarak başlat:

pg_ctl -D /usr/local/var/postgres start
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.