다른 사람이 연결될 수있는 동안 강제 삭제 DB


103

PostgreSQL DB 클러스터에서 데이터베이스를 제거해야합니다. 활성 연결이 있어도 어떻게해야합니까? -force모든 연결을 끊은 다음 DB를 삭제 하는 일종의 플래그 가 필요합니다 .

어떻게 구현할 수 있습니까?

dropdb현재 사용 하고 있지만 다른 도구가 가능합니다.

답변:


154

PostgreSQL * 에서는 클라이언트가 연결되어있는 동안 데이터베이스를 삭제할 수 없습니다.

적어도 dropdb유틸리티가 아닌 DROP DATABASE서버 쿼리 주위의 간단한 래퍼 일뿐 입니다.

매우 강력한 해결 방법은 다음과 같습니다.

또는 다른 클라이언트를 사용하여 서버에 수퍼 유저 로 연결하십시오 psql. 마십시오 하지 당신이 드롭 할 데이터베이스를 사용합니다.

psql -h localhost postgres postgres

이제 일반 데이터베이스 클라이언트를 사용하면 세 가지 간단한 단계를 통해 데이터베이스를 강제로 삭제할 수 있습니다.

  1. 이 데이터베이스에 아무도 연결할 수 없는지 확인하십시오. 다음 방법 중 하나를 사용할 수 있습니다 (두 번째 방법은 더 안전 해 보이지만 수퍼 유저의 연결을 막지는 않습니다).

    /* 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. 을 사용하여이 데이터베이스에 연결된 모든 클라이언트의 연결을 강제로 끊습니다 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. 데이터베이스를 삭제하십시오.

    DROP DATABASE mydb;

1 단계 에는 첫 번째 방법에 대한 수퍼 유저 권한과 두 번째 방법에 대한 데이터베이스 소유자 권한이 필요합니다. 2 단계에는 수퍼 유저 권한이 필요합니다 . 3 단계에는 데이터베이스 소유자 권한이 필요 합니다 .


* 이것은 모든 버전의 PostgreSQL, 버전 11까지 적용됩니다.



그래서 내가 뭘 잘못했는지 모르지만 이제는 내가 목표로 한 데이터베이스에 연결할 수 없습니다! "유지 관리 데이터베이스를 삭제할 수 없습니다"라고 표시된대로 삭제할 수도 없습니다.
Matt Skeldon

@MattSkeldon,이 메시지가 무엇을 의미하는지 전혀 모른다. vanilla PostgreSQL에서는 template0 및 template1을 제외한 모든 데이터베이스를 삭제할 수 있습니다. 무료가 아닌 상용 버전을 사용하고 있습니까? 서버 문제가 아닌 클라이언트 문제 일 수 있습니까? psql을 사용해 보셨습니까?
filiprem

불행히도 나는 SQL 배경에서 왔으며 상업용이 아닌 무료 상태로 인해 PGSQL을 사용하고 있습니다.
Matt Skeldon

좀비 세션이 오래 지속되는 곳에서는 작동하지 않습니다. pg_terminate_backend ()는 해당 세션을 죽이지 않기 때문에 여전히해야 할 일에 약간 갇혀 있습니다. Postgres su이지만 실행중인 서버에 액세스 할 수 없습니다.
Alexander

6

쉘 유틸리티를 사용하여이 작업을 수행 할 수있는 방법 dropdbpg_ctl(또는 pg_ctlcluster데비안 및 유도체 인은). 그러나 @filiprem의 방법 여러 가지 이유로 우수 합니다.

  • 문제의 데이터베이스에서만 사용자를 연결 해제합니다.
  • 전체 클러스터를 다시 시작할 필요는 없습니다.
  • 즉각적인 재 연결을 방지하여 dropdb명령을 망칠 수 있습니다 .

나는 인용한다 man pg_ctlcluster:

--force"빠른"모드 옵션을 사용하면 모든 활성 트랜잭션을 롤백하고 클라이언트를 즉시 연결 해제하여 완전히 종료합니다. 그래도 작동하지 않으면 "즉시"모드에서 시스템 종료가 다시 시도되어 클러스터가 일관성이없는 상태가되어 다음 시작시 복구가 실행됩니다. 그래도 문제가 해결되지 않으면 포스트 마스터 프로세스가 종료됩니다. 성공하면 0으로, 서버가 실행 중이 지 않으면 2로, 다른 실패 조건에서는 1로 종료합니다. 이 모드는 기계를 종료하려고 할 때만 사용해야합니다.

pg_ctlcluster 9.1 main restart --force

또는

pg_ctl restart -D datadir -m fast

또는

pg_ctl restart -D datadir -m immediate

바로 뒤에 :

dropdb mydb

아마도 즉각적인 승계를 위해 대본에서.


4
전체 postgres 인스턴스를 시작하므로 이상적이지 않을뿐만 아니라 작동이 보장되지는 않습니다. 서버를 다시 시작한 후 dropdb를 다시 실행하는 시간 사이에 클라이언트가 연결될 수 있습니다. 위의 @filiprem의 답변은 연결을 끊기 전에 데이터베이스에 대한 모든 연결을 비활성화하고 다른 데이터베이스를 유지합니다.
Jim Mitchener

6

내 경우에는 @filiprem의 답변을 사용하고 단순화 :

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

데이터베이스가없는 연결을 선택하여 DB에 연결 한 RDS와 같은 경우 기본적으로이 변형을 수행하여 마지막으로 열린 연결이 될 수 있습니다.

 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;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.