it-swarm.asia

Paksa jatuhkan db sementara yang lain mungkin terhubung

Saya perlu menghapus database dari klaster DB PostgreSQL. Bagaimana saya bisa melakukannya walaupun ada koneksi aktif? Saya perlu semacam -force flag, yang akan menjatuhkan semua koneksi dan kemudian DB.

Bagaimana saya bisa menerapkannya?

Saya menggunakan dropdb saat ini, tetapi alat lain dimungkinkan.

126
Alex

Di PostgreSQL*, Anda tidak dapat menjatuhkan basis data saat klien terhubung dengannya.

Setidaknya, tidak dengan utilitas dropdb - yang hanya merupakan pembungkus sederhana DROP DATABASE permintaan server.

Solusi yang cukup kuat berikut:

Hubungkan ke server Anda sebagai superuser , menggunakan psql atau klien lain. Do not menggunakan database yang ingin Anda jatuhkan.

psql -h localhost postgres postgres

Sekarang menggunakan klien database biasa, Anda dapat memaksa drop database menggunakan tiga langkah sederhana:

  1. Pastikan tidak ada yang bisa terhubung ke database ini. Anda dapat menggunakan salah satu metode berikut (yang kedua tampaknya lebih aman, tetapi tidak mencegah koneksi dari pengguna super).

    /* 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. Memutuskan sambungan semua klien yang terhubung ke database ini, menggunakan 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. Jatuhkan basis data.

    DROP DATABASE mydb;
    

Langkah 1 membutuhkan superuser hak istimewa untuk metode 1, dan pemilik basis data hak istimewa untuk yang ke-2. Langkah 2 membutuhkan superuser hak istimewa. Langkah 3 membutuhkan pemilik basis data hak istimewa.


Ini berlaku untuk semua versi PostgreSQL, hingga versi 12. Versi 13 memiliki DROP DATABASE mydb FORCE


178
filiprem

Menggunakan jawaban @ filiprem dalam kasus saya dan menyederhanakannya:

-- 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
9
Dorian

There is cara untuk melakukan ini dengan utilitas Shell dropdb & pg_ctl (atau pg_ctlcluster dalam bahasa Debian dan turunannya). Tetapi @ metode filiprem lebih unggul karena beberapa alasan:

  • Itu hanya memutus pengguna dari database yang dimaksud.
  • Tidak perlu me-restart seluruh cluster.
  • Itu mencegah koneksi ulang segera, mungkin merusak perintah dropdb.

Saya mengutip man pg_ctlcluster:

Dengan --force pilihan mode "cepat" digunakan yang memutar kembali semua transaksi aktif, segera memutuskan klien dan dengan demikian dimatikan dengan bersih. Jika itu tidak berhasil, shutdown akan dicoba lagi dalam mode "langsung", yang dapat membuat cluster dalam keadaan tidak konsisten dan dengan demikian akan mengarah pada pemulihan di awal berikutnya. Jika ini masih tidak membantu, proses postmaster terbunuh. Keluar dengan 0 pada keberhasilan, dengan 2 jika server tidak berjalan, dan dengan 1 pada kondisi kegagalan lainnya. Mode ini seharusnya hanya digunakan ketika mesin akan dimatikan.

pg_ctlcluster 9.1 main restart --force

atau

pg_ctl restart -D datadir -m fast

atau

pg_ctl restart -D datadir -m immediate

segera diikuti oleh:

dropdb mydb

Mungkin dalam naskah untuk suksesi segera.

7

Jika Anda menggunakan sesuatu seperti RDS di mana koneksi tanpa database yang dipilih menempatkan Anda ke dalam DB yang Anda minta dibuat secara default, Anda dapat melakukan varian ini untuk menjadikan diri Anda sebagai koneksi terbuka terakhir.

 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;
0
Jharwood