Как удалить базу данных PostgreSQL, если есть активные подключения к ней?

Не скажу что PostgreSQL какой-то падучий или проблемный, но перебои электропитания или неполадки оборудования могут завалить что-угодно. А при починке проблем в базах PostgreSQL, я пришел к выводу что проще и быстрее всего просто задампить проблемную базу, удалить, создать заново и восстановить из дампа. Однозначно получается быстрее. Особенно если еще и автоматизировать таким скриптом:

#!/bin/sh

DB=DBNAME
TMP=/tmp/dbdump.sql

echo dumping $DB
pg_dump $DB > $TMP
echo droping $DB
dropdb $DB
echo creating $DB
createdb $DB
echo restoring $DB
psql -f $TMP $DB

Но статья не о починках баз и не соревнованиях по удалению/восстановлению, а том что базу вы можете и не удалить, если будут подключения к БД. А они наверняка будут! Иначе к чему тогда спешить с починкой!? Поэтому разберемся как же нам завершить все подключения.

Можно повыключать другие приложения, подключающиеся к базе, или зафаерволиться, но проще и быстрее все сделать одним единственным запросом к БД.

Сборщик статистики PostgreSQL поддерживает сбор и отчетность о деятельности сервера. Представление pg_stat_activity содержит всю необходимую информацию о процессах подключений к серверу.

Составить запрос для завершения всех подключений к БД с именем DBNAME, за исключением нашего, не составит труда:

SELECT pg_terminate_backend(pg_stat_activity.pid) 
FROM pg_stat_activity 
WHERE datname='$DBNAME' AND pid<>pg_backend_pid();

Функция pg_terminate_backend() завершает подключения по PID процесса, который мы выбрали из представления pg_stat_activity. В условии указали интересующую базу и исключили PID «нашего» процесса.

Для PostgreSQL версии 9.1 и ниже запрос будет немножко другой:

SELECT pg_terminate_backend(pg_stat_activity.procpid) 
FROM pg_stat_activity 
WHERE datname='$DBNAME' AND procpid<>pg_backend_pid();

Ну и скрипт тогда до ума доведем:

#!/bin/sh

DB=DBNAME
TMP=/tmp/dbdump.sql

echo dumping $DB
pg_dump $DB > $TMP

echo terminate active connections
echo try method for 9.2 and above...
echo "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE datname='$DB' AND pid<>pg_backend_pid();" | psql $DB
echo try method for 9.1 and below...
echo "SELECT pg_terminate_backend(pg_stat_activity.procpid) FROM pg_stat_activity WHERE datname='$DB' AND procpid<>pg_backend_pid();" | psql $DB

echo droping $DB
dropdb $DB
echo creating $DB
createdb $DB
echo restoring $DB
psql -f $TMP $DB

Отмечу что в скрипте мы попытаемся выполнить оба запроса: для новых и старых версий, ведь один из них выполнится успешно, а определять версию сервера больно накладно будет.


Комментарии

Оставить комментарий

Ответ на Как удалить базу данных PostgreSQL, если есть активные подключения к ней?