PostgreSQL-DB에 대한 자동 연결로 인해 데이터베이스를 삭제할 수 없습니다


161

데이터베이스를 삭제하려고 할 때마다 다음을 얻습니다.

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

내가 사용할 때 :

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

해당 DB에서 연결을 종료했지만 그 후에 데이터베이스를 삭제하려고하면 누군가 자동으로 해당 데이터베이스에 연결 하여이 오류가 발생합니다. 무엇을 할 수 있습니까? 나 외에는 아무도이 데이터베이스를 사용하지 않습니다.

답변:


194

향후 연결을 방지 할 수 있습니다.

REVOKE CONNECT ON DATABASE thedb FROM public;

(그리고 아마도 다른 사용자 / 역할; 참조 \l+에서 psql)

그런 다음 자신을 제외하고이 db에 대한 모든 연결을 종료 할 수 있습니다.

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

이전 버전에서는 pid호출 procpid되었으므로 처리해야합니다.

CONNECT권한을 철회했기 때문에 자동 연결을 시도한 모든 것이 더 이상 그렇게 할 수 없습니다.

이제 DB를 삭제할 수 있습니다.

정상적인 작업에 수퍼 유저 연결을 사용하는 경우에는 작동하지 않지만 그렇게하려면 먼저 해당 문제를 해결해야합니다.


데이터베이스 삭제를 완료 한 후 데이터베이스를 다시 작성하면 아래 명령을 실행하여 액세스를 복원 할 수 있습니다.

GRANT CONNECT ON DATABASE thedb TO public;

19
나중에 같은 이름의 다른 데이터베이스를 가져올 경우, 공공 뒷면에 연결 기능을 부여 :GRANT CONNECT ON DATABASE thedb TO public;
미하일 Vasin

155

데이터베이스를 삭제하려고 할 때마다 다음을 얻습니다.

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

먼저 취소해야합니다

REVOKE CONNECT ON DATABASE TARGET_DB FROM public;

그런 다음 사용하십시오.

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

반드시 작동합니다.


5
이것은 나를 위해 그것을했다. 감사합니다
rpivovar

에 딱 맞다! 감사합니다! 🎉
slajma

완벽하게 작동했습니다. 감사합니다.
Mustafa Magdi

34

이 문제에 대한 해결책을 찾았습니다. 터미널 에서이 명령을 실행하십시오.

ps -ef | grep postgres

이 명령으로 프로세스를 종료하십시오.

sudo kill -9 PID

아니요, 너무 하드 코드입니다. 액세스중인 다른 데이터베이스가 있기 때문에 pg 프로세스를 킬 수 없다면 어떻게해야합니까?
Vladimir Stazhilov

2
@VladimirStazhilov 해당 데이터베이스의 데이터베이스 이름과 pid를 표시합니다. 누군가 특정 데이터베이스 만 특정 pid kill을 선택할 수 있습니다.
Dinesh Pallapa

29

연결이 어디에서 왔는지 확인하십시오. 이 모든 것을 다음에서 볼 수 있습니다.

select * from pg_stat_activity where datname = 'TARGET_DB';

아마도 당신의 연결입니까?


4
결과를 본 후 터미널에서 sudo kill -9 PID
Dan Rey Oquindo

25

다른 사용자가 데이터베이스에 액세스하고 있음을 의미합니다. PostgreSQL을 다시 시작하면됩니다. 이 명령은 트릭을 수행합니다

root@kalilinux:~#sudo service postgresql restart

그런 다음 데이터베이스를 삭제하십시오.

postgres=# drop database test_database;

이것은 트릭을 할 것입니다.


11

UI를 사용한 pgAdmin 4 솔루션

다음을 수행하지 않은 경우 먼저 대시 보드에서 활동 표시를 활성화하십시오.

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

이제 db를 사용하여 모든 프로세스를 비활성화하십시오.

  1. DB 이름을 클릭하십시오
  2. 대시 보드> 세션을 클릭하십시오.
  3. 새로 고침 아이콘 클릭
  4. 각 프로세스 옆의 삭제 (x) 아이콘을 클릭하여 종료하십시오.

이제 db를 삭제할 수 있습니다.


이것은 잘 작동합니다-Visual C ++ 빌드 1914, 64 비트 (Windows)로 컴파일 된 PgAdmin 4.5 및 PostgreSQL 11.2로 테스트했습니다.
vab2048

2
이것이 내가 생각하는 최고의 솔루션입니다. 이것은 정말 잘 작동합니다!
Lahiru

10

컴퓨터의 다른 서비스에 영향을 미치지 않으면 간단히 service postgresql restart


8

해결 방법 :
1. Pg 서버를 종료합니다 . 2. 모든 활성 연결이 끊어집니다. 3. Pg 서버를 다시 시작합니다 . 4. 명령을 시도합니다
여기에 이미지 설명을 입력하십시오




이것은 Mac의 Postgress.app에서도 저에게 효과적이었습니다. 이 경우 서버를 중지 / 시작하십시오
Juan José Ramírez

7

그렇게 간단

sudo service postgresql restart

3

필자의 경우 AWS Redshift (Postgres 기반)를 사용하고 있습니다. 그리고 DB에 대한 다른 연결이없는 것처럼 보이지만 동일한 오류가 발생합니다.

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

필자의 경우 데이터베이스 클러스터가 여전히 데이터베이스에서 일부 처리를 수행하는 것 같고 다른 외부 / 사용자 연결은 없지만 데이터베이스는 여전히 내부적으로 사용 중입니다. 나는 다음을 실행하여 이것을 발견했다.

SELECT * FROM stv_sessions;

그래서 내 핵은 코드에 루프를 작성하여 데이터베이스 이름이있는 행을 찾는 것이 었습니다. (물론 루프는 무한하지 않으며 졸린 루프 등입니다)

SELECT * FROM stv_sessions where db_name = 'XYZ';

행이 발견되면 각 PID를 하나씩 삭제하십시오.

SELECT pg_terminate_backend(PUT_PID_HERE);

행을 찾을 수 없으면 데이터베이스를 삭제하십시오.

DROP DATABASE XYZ;

참고 : 필자의 경우 Java 단위 / 시스템 테스트를 작성 중이며 허용 가능한 것으로 간주됩니다. 프로덕션 코드에는 허용되지 않습니다.


다음은 Java로 된 완전한 해킹입니다 (내 테스트 / 유틸리티 클래스는 무시하십시오).

  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

제 생각에는 backgroud에서 유휴 쿼리가 실행되고 있습니다.

  1. 실행중인 쿼리를 먼저 표시해보십시오
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. 유휴 쿼리 종료 (문제가있는 데이터베이스를 참조하고 있는지 확인하거나 선택한 결과에서 pid를 사용하여 모든 데이터베이스를 종료하거나 특정 종료 할 수 있음)

SELECT pg_terminate_backend (procpid);

참고 : 선택 쿼리를 종료해도 아무런 영향이 없습니다.


2

REVOKE CONNECTDB 소유자 또는 수퍼 유저로부터의 연결을 막지 않습니다. 따라서 다른 사람이 db를 연결하지 못하게하려면 follow 명령이 유용 할 수 있습니다.

alter database pilot allow_connections = off;

그런 다음 사용하십시오.

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

1
고마워요 ... REVOKE CONNECT가 충분하지 않았습니다.
volpato

1

다른 경우에 유용한 두 가지 상위 답변이 유용하다는 것을 알았지 만 오늘이 문제를 해결하는 가장 간단한 방법은 PyCharm이 세션을 계속 열어두고 StopPyCharm을 클릭하면 도움 이 될 수 있음을 인식하는 것이 었습니다 . 브라우저에서 pgAdmin4를 열면 거의 즉시 데이터베이스 세션 통계가 0으로 떨어지는 것을 보았습니다.이 시점에서 데이터베이스를 삭제할 수있었습니다.


"PyCharm이 세션을 열린 상태로 유지했을 수 있습니다"? 어떻게? PyCharm의 터미널 (peewee, backend Postgres가있는 프론트 엔드 Python)에서 단위 테스트를 실행합니다. 즉, "Stop"버튼이 회색으로 표시되어 있습니다. 그럼에도 불구하고 이러한 오류가 계속 발생합니다.
Laryx Decidua

@LaryxDecidua 필자의 경우 PyCharm에서 db를 사용하는 서비스 인스턴스가 있어야한다고 생각합니다. PyCharm을 종료하면 인스턴스 수가 0으로 떨어지고 db를 삭제할 수 있습니까? 그렇다면 여전히 연결된 무언가 (데이터베이스 탐색기, SQL 쿼리 등)가 있어야합니다.
hlongmore

1

macOS에서 다음 명령을 사용하여 콘솔을 통해 postgresql 데이터베이스를 다시 시작하십시오.

brew services restart postgresql

-1

터미널에서 다음 명령을 시도하십시오.

ps -ef | grep postgres

당신은 다음과 같이 보일 것입니다 :

501 1445 3645 0 12:05 AM 0 : 00.03 postgres : sasha dbname [local] 유휴

세 번째 숫자 (3645)는 PID입니다.

이것을 삭제할 수 있습니다

sudo kill -9 3645

그런 다음 PostgreSQL 연결을 시작하십시오.

수동으로 시작하십시오.

pg_ctl -D /usr/local/var/postgres start
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.