Мне нужно написать скрипт, который удалит базу данных PostgreSQL. С ним может быть много связей, но скрипт должен это игнорировать.
Стандартный DROP DATABASE db_name
запрос не работает при открытых соединениях.
Как я могу решить проблему?
Мне нужно написать скрипт, который удалит базу данных PostgreSQL. С ним может быть много связей, но скрипт должен это игнорировать.
Стандартный DROP DATABASE db_name
запрос не работает при открытых соединениях.
Как я могу решить проблему?
Ответы:
Это приведет к удалению существующих подключений, кроме вашего:
Запросите pg_stat_activity
и получите значения pid, которые хотите убить, а затем введите SELECT pg_terminate_backend(pid int)
их.
PostgreSQL 9.2 и выше:
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB' -- ← change this to your DB
AND pid <> pg_backend_pid();
PostgreSQL 9.1 и ниже:
SELECT pg_terminate_backend(pg_stat_activity.procpid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'TARGET_DB' -- ← change this to your DB
AND procpid <> pg_backend_pid();
После того, как вы отключите всех, вам придется отключить и выполнить команду DROP DATABASE из соединения с другой базой данных, а не той, которую вы пытаетесь сбросить.
Обратите внимание на переименование procpid
столбца в pid
. Смотрите эту ветку списка рассылки .
; drop database TARGET_DB;
в моем случае это работало хорошо, чтобы убедиться, что база данных исчезла к тому времени, когда все начало повторяться.
dropdb --force
.
В PostgreSQL 9.2 и выше отключить все, кроме сеанса, от базы данных, к которой вы подключены:
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE datname = current_database()
AND pid <> pg_backend_pid();
В старых версиях то же самое, просто измените pid
на procpid
. Чтобы отключиться от другой базы данных, просто измените current_database()
имя базы данных, от которой вы хотите отключить пользователей.
Вы можете REVOKE
в CONNECT
праве от пользователей базы данных перед отключением пользователей, в противном случае пользователи будут просто держать на Reconnecting и вы никогда не получите шанс понизить БД. Посмотрите этот комментарий и вопрос, с которым он связан, как мне отсоединить всех других пользователей от базы данных .
Если вы просто хотите отключить незанятых пользователей, посмотрите этот вопрос .
Вы можете уничтожить все соединения перед удалением базы данных, используя pg_terminate_backend(int)
функцию.
Вы можете получить все запущенные бэкэнды, используя системное представление pg_stat_activity
Я не совсем уверен, но следующее, вероятно, убьет все сессии:
select pg_terminate_backend(procpid)
from pg_stat_activity
where datname = 'doomed_database'
Конечно, вы не можете быть подключены к этой базе данных
В зависимости от вашей версии postgresql вы можете столкнуться с ошибкой, которая делает pg_stat_activity
за которой пропускаются активные соединения от сброшенных пользователей. Эти соединения также не показаны внутри pgAdminIII.
Если вы выполняете автоматическое тестирование (в котором вы также создаете пользователей), это может быть вероятным сценарием.
В этом случае вам нужно вернуться к таким запросам, как:
SELECT pg_terminate_backend(procpid)
FROM pg_stat_get_activity(NULL::integer)
WHERE datid=(SELECT oid from pg_database where datname = 'your_database');
ПРИМЕЧАНИЕ. В версии 9.2+ вам нужно изменить procpid
на pid
.
procpid
на pid
этот фрагмент работает на 9.3.
Я заметил, что postgres 9.2 теперь вызывает pid столбца, а не procpid.
Я склонен называть это из оболочки:
#!/usr/bin/env bash
# kill all connections to the postgres server
if [ -n "$1" ] ; then
where="where pg_stat_activity.datname = '$1'"
echo "killing all connections to database '$1'"
else
echo "killing all connections to database"
fi
cat <<-EOF | psql -U postgres -d postgres
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
${where}
EOF
Надеюсь, что это полезно. Спасибо @JustBob за sql.
В командной строке Linux я бы сначала остановил все запущенные процессы postgresql, связав эту команду sudo /etc/init.d/postgresql restart
введите команду bg, чтобы проверить, работают ли другие процессы postgresql
затем следует dropdb dbname для удаления базы данных
sudo /etc/init.d/postgresql restart
bg
dropdb dbname
Это работает для меня в командной строке Linux
PostgreSQL 9.2 и выше:
SELECT pg_terminate_backend(pid)FROM pg_stat_activity WHERE datname = 'YOUR_DATABASE_NAME_HERE'
Вот мой хак ... = D
# Make sure no one can connect to this database except you!
sudo -u postgres /usr/pgsql-9.4/bin/psql -c "UPDATE pg_database SET datallowconn=false WHERE datname='<DATABASE_NAME>';"
# Drop all existing connections except for yours!
sudo -u postgres /usr/pgsql-9.4/bin/psql -c "SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '<DATABASE_NAME>' AND pid <> pg_backend_pid();"
# Drop database! =D
sudo -u postgres /usr/pgsql-9.4/bin/psql -c "DROP DATABASE <DATABASE_NAME>;"
Я поставил этот ответ, потому что включить команду (выше), чтобы заблокировать новые подключения и потому, что любая попытка с командой ...
REVOKE CONNECT ON DATABASE <DATABASE_NAME> FROM PUBLIC, <USERS_ETC>;
... не работает, чтобы заблокировать новые подключения!
Спасибо @araqnid @GoatWalker! = D
Предстоящий PostgreSQL 13 представит FORCE
опцию.
DROP DATABASE удаляет базу данных ... Кроме того, если кто-либо еще подключен к целевой базе данных, эта команда не будет выполнена, если вы не используете опцию FORCE, описанную ниже.
FORCE
Попытайтесь разорвать все существующие соединения с целевой базой данных. Он не завершается, если в целевой базе данных присутствуют подготовленные транзакции, активные слоты логической репликации или подписки.
DROP DATABASE db_name WITH (FORCE);
В моем случае мне пришлось выполнить команду, чтобы сбросить все соединения, включая мое активное соединение администратора
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE datname = current_database()
который разорвал все соединения и показал мне фатальное сообщение об ошибке:
FATAL: terminating connection due to administrator command SQL state: 57P01
После этого можно было сбросить базу данных