Force drop db, в то время как другие могут быть подключены
104
Мне нужно удалить базу данных из кластера PostgreSQL DB. Как я могу это сделать, даже если есть активные подключения? Мне нужен своего рода -forceфлаг, который будет сбрасывать все соединения, а затем БД.
Как я могу это реализовать?
Я использую в dropdbнастоящее время, но возможны и другие инструменты.
В PostgreSQL * вы не можете удалить базу данных, когда к ней подключены клиенты.
По крайней мере, не с помощью dropdbутилиты, которая является простой оболочкой DROP DATABASEдля запроса к серверу.
Весьма надежный обходной путь выглядит следующим образом:
Подключайтесь к вашему серверу как суперпользователь , используя psqlили другой клиент. Как не использовать базу данных , которую вы хотите отказаться.
psql -h localhost postgres postgres
Теперь, используя простой клиент базы данных, вы можете принудительно удалить базу данных, выполнив три простых шага:
Убедитесь, что никто не может подключиться к этой базе данных. Вы можете использовать один из следующих методов (второй кажется более безопасным, но не мешает соединениям от суперпользователей).
/* 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; */
Принудительное отключение всех клиентов, подключенных к этой базе данных, используя pg_terminate_backend.
SELECT pg_terminate_backend(pid)FROM pg_stat_activityWHERE 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'; */
Удалите базу данных.
DROPDATABASE mydb;
Шаг 1 требует привилегий суперпользователя для 1-го метода и привилегий владельца базы данных для 2-го. Шаг 2 требует привилегий суперпользователя . Шаг 3 требует привилегии владельца базы данных .
* Это относится ко всем версиям PostgreSQL, вплоть до версии 11.
Так что я не знаю, что я сделал неправильно, но теперь я даже не могу подключиться к целевой базе данных! Я также не могу отбросить его, поскольку там написано: «База данных обслуживания не может быть удалена»
Мэтт Скелдон,
@MattSkeldon, понятия не имею, что означает это сообщение. В ванильном PostgreSQL вы можете удалить любую базу данных, кроме template0 и template1. Может быть, вы используете какую-то несвободную / коммерческую версию? Может быть, это проблема клиента, а не сервера? Ты пробовал psql?
filiprem
К сожалению, я пришел из SQL, используя PGSQL из-за некоммерческого / свободного статуса.
Мэтт Скелдон
Это не работает для меня, где есть продолжительные сессии зомби. pg_terminate_backend () не убивает эти сессии, поэтому я все еще немного застрял в том, что делать: я - Postgres su, но у меня нет доступа к серверу, на котором он работает.
Александр
6
Там является способ сделать это с помощью утилиты оболочки dropdbи pg_ctl(или pg_ctlclusterв Debian и дериватов). Но метод @ filiprem лучше по нескольким причинам:
Это только отключает пользователей от рассматриваемой базы данных.
Не нужно перезагружать весь кластер.
Это предотвращает немедленное переподключение, возможно, портит dropdbкоманду.
Я цитирую man pg_ctlcluster:
С --forceопцией используется «быстрый» режим, который откатывает все активные транзакции, немедленно отключает клиентов и, таким образом, корректно завершает работу. Если это не сработает, попытка выключения будет предпринята снова в «немедленном» режиме, который может привести кластер в несогласованное состояние и, таким образом, привести к запуску восстановления при следующем запуске. Если это по-прежнему не помогает, процесс postmaster убивается. Выход с 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
Возможно в сценарии для немедленной преемственности.
Мало того, что это не идеально, так как он запускает полный экземпляр postgres, но он не гарантированно работает. Клиент может установить соединение между моментом перезапуска сервера и повторной попытки запуска dropdb. Ответ @filiprem, приведенный выше, отключает все подключения к базе данных перед отключением и будет поддерживать другие базы данных.
Джим Митченер
6
Используя ответ @ filiprem в моем случае и упростив его:
-- Connecting to the current user localhost's postgres instance
psql-- Making sure the database existsSELECT*from pg_database where datname ='my_database_name'-- Disallow new connectionsUPDATE pg_database SET datallowconn ='false'WHERE datname ='my_database_name';ALTERDATABASE my_database_name CONNECTION LIMIT 1;-- Terminate existing connectionsSELECT pg_terminate_backend(pid)FROM pg_stat_activity WHERE datname ='my_database_name';-- Drop databaseDROPDATABASE my_database_name
Если вы работаете с чем-то вроде RDS, где соединения без выбранной базы данных помещают вас в БД, которую вы просили создать по умолчанию, вы можете сделать этот вариант, чтобы обойти себя как последнее открытое соединение.
Там является способ сделать это с помощью утилиты оболочки
dropdb
иpg_ctl
(илиpg_ctlcluster
в Debian и дериватов). Но метод @ filiprem лучше по нескольким причинам:dropdb
команду.Я цитирую
man pg_ctlcluster
:или же
или же
сразу же после:
Возможно в сценарии для немедленной преемственности.
источник
Используя ответ @ filiprem в моем случае и упростив его:
источник
Если вы работаете с чем-то вроде RDS, где соединения без выбранной базы данных помещают вас в БД, которую вы просили создать по умолчанию, вы можете сделать этот вариант, чтобы обойти себя как последнее открытое соединение.
источник