Buộc thả db trong khi những người khác có thể được kết nối


103

Tôi cần xóa cơ sở dữ liệu khỏi cụm DB PostgreSQL. Làm thế nào tôi có thể làm điều đó ngay cả khi có kết nối hoạt động? Tôi cần một loại -forcecờ, nó sẽ bỏ tất cả các kết nối và sau đó là DB.

Làm thế nào tôi có thể thực hiện nó?

Tôi đang sử dụng dropdb, nhưng các công cụ khác là có thể.

Câu trả lời:


154

Trong PostgreSQL * , bạn không thể bỏ cơ sở dữ liệu trong khi máy khách được kết nối với nó.

Ít nhất, không phải với dropdbtiện ích - mà chỉ là một trình bao bọc đơn giản xung quanh DROP DATABASEtruy vấn máy chủ.

Cách giải quyết khá mạnh mẽ sau:

Kết nối với máy chủ của bạn dưới dạng siêu người dùng , sử dụng psqlhoặc ứng dụng khách khác. Đừng không sử dụng cơ sở dữ liệu bạn muốn thả.

psql -h localhost postgres postgres

Bây giờ bằng cách sử dụng máy khách cơ sở dữ liệu đơn giản, bạn có thể buộc thả cơ sở dữ liệu bằng ba bước đơn giản:

  1. Hãy chắc chắn rằng không ai có thể kết nối với cơ sở dữ liệu này. Bạn có thể sử dụng một trong các phương pháp sau (cách thứ hai có vẻ an toàn hơn, nhưng không ngăn chặn kết nối từ siêu nhân).

    /* 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. Buộc ngắt kết nối tất cả các máy khách được kết nối với cơ sở dữ liệu này, bằng cách sử dụng 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. Thả cơ sở dữ liệu.

    DROP DATABASE mydb;

Bước 1 yêu cầu đặc quyền siêu người dùng cho phương thức 1 và đặc quyền chủ sở hữu cơ sở dữ liệu cho phương thức thứ hai. Bước 2 yêu cầu đặc quyền siêu người dùng . Bước 3 yêu cầu đặc quyền chủ sở hữu cơ sở dữ liệu .


* Điều này áp dụng cho tất cả các phiên bản của PostgreSQL, cho đến phiên bản 11.



Vì vậy, tôi không biết mình đã làm gì sai, nhưng giờ tôi thậm chí không thể kết nối với cơ sở dữ liệu mà tôi đã nhắm mục tiêu! Tôi cũng không thể bỏ nó vì nó nói "Cơ sở dữ liệu bảo trì không thể bị hủy"
Matt Skeldon

@MattSkeldon, không biết thông điệp này có ý nghĩa gì. Trong vanilla PostgreSQL, bạn có thể loại bỏ bất kỳ cơ sở dữ liệu nào ngoại trừ template0 & template1. Có thể bạn sử dụng một số phiên bản không miễn phí / thương mại? Có lẽ đó là vấn đề máy khách không phải vấn đề máy chủ? Bạn đã thử psql chưa?
filiprem

Thật không may, tôi đến từ một nền tảng SQL, sử dụng PGQuery đang được sử dụng do trạng thái phi thương mại / miễn phí.
Matt Skeldon

Điều này không phù hợp với tôi khi có các phiên zombie kéo dài. pg_terminate_backend () không giết các phiên đó vì vậy tôi vẫn hơi bế tắc về việc phải làm: Tôi là một Postgres su, nhưng tôi không có quyền truy cập vào máy chủ đang chạy.
Alexander

6

một cách để làm điều này với các tiện ích vỏ dropdb& pg_ctl(hoặc pg_ctlclustertrong Debian và derivates). Nhưng phương pháp của @ filiprem là vượt trội vì nhiều lý do:

  • Nó chỉ ngắt kết nối người dùng khỏi cơ sở dữ liệu trong câu hỏi.
  • Nó không cần phải khởi động lại toàn bộ cụm.
  • Nó ngăn chặn kết nối lại ngay lập tức, có thể làm hỏng dropdblệnh.

Tôi trích dẫn man pg_ctlcluster:

Với --forcetùy chọn, chế độ "nhanh" được sử dụng để khôi phục tất cả các giao dịch đang hoạt động, ngắt kết nối khách hàng ngay lập tức và do đó tắt hoàn toàn. Nếu điều đó không hoạt động, tắt máy được thử lại ở chế độ "ngay lập tức", điều này có thể khiến cụm ở trạng thái không nhất quán và do đó sẽ dẫn đến quá trình khôi phục ở lần khởi động tiếp theo. Nếu điều này vẫn không giúp ích, quá trình bưu điện bị giết. Thoát với 0 khi thành công, với 2 nếu máy chủ không chạy và với 1 trên các điều kiện lỗi khác. Chế độ này chỉ nên được sử dụng khi máy sắp tắt.

pg_ctlcluster 9.1 main restart --force

hoặc là

pg_ctl restart -D datadir -m fast

hoặc là

pg_ctl restart -D datadir -m immediate

ngay lập tức theo sau:

dropdb mydb

Có thể trong một kịch bản cho sự thành công ngay lập tức.


4
Điều này không chỉ ít hơn lý tưởng vì nó khởi động toàn bộ postgres mà còn không được đảm bảo để hoạt động. Máy khách có thể kết nối giữa thời gian bạn khởi động lại máy chủ và cố gắng chạy lại dropdb. Câu trả lời của @filiprem ở trên sẽ vô hiệu hóa tất cả các kết nối đến cơ sở dữ liệu trước khi ngắt kết nối và sẽ duy trì các cơ sở dữ liệu khác.
Jim Mitchener

6

Sử dụng câu trả lời của @ filiprem trong trường hợp của tôi và đơn giản hóa nó:

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

Nếu bạn đang sử dụng RDS, nơi các kết nối không có cơ sở dữ liệu được chọn sẽ đưa bạn vào DB mà bạn yêu cầu được tạo theo mặc định, bạn có thể thực hiện biến thể này để nhận ra mình là kết nối mở cuối cùng.

 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;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.