Force drop db enquanto outros podem estar conectados
104
Preciso remover um banco de dados de um cluster do PostgreSQL DB. Como posso fazer isso mesmo se houver conexões ativas? Preciso de um tipo de -forcesinalizador, que abandone todas as conexões e depois o banco de dados.
Como posso implementá-lo?
Estou usando dropdbatualmente, mas outras ferramentas são possíveis.
No PostgreSQL * , você não pode eliminar um banco de dados enquanto os clientes estiverem conectados a ele.
Pelo menos, não com o dropdbutilitário - que é apenas um invólucro simples em torno da DROP DATABASEconsulta ao servidor.
Solução alternativa bastante robusta a seguir:
Conecte-se ao seu servidor como superusuário , usando psqlou outro cliente. Você não usar o banco de dados que você quer deixar cair.
psql -h localhost postgres postgres
Agora, usando o cliente de banco de dados simples, você pode forçar o descarte do banco de dados usando três etapas simples:
Verifique se ninguém pode se conectar a este banco de dados. Você pode usar um dos seguintes métodos (o segundo parece mais seguro, mas não impede as conexões dos superusuários).
/* 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; */
Forçar a desconexão de todos os clientes conectados a esse banco de dados usando 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'; */
Solte o banco de dados.
DROPDATABASE mydb;
A Etapa 1 requer privilégios de superusuário para o 1º método e privilégios de proprietário do banco de dados para o 2º. A etapa 2 requer privilégios de superusuário . Etapa 3 requer privilégio de proprietário do banco de dados .
* Isso se aplica a todas as versões do PostgreSQL, até a versão 11.
Portanto, não sei o que fiz de errado, mas agora não consigo nem me conectar ao banco de dados que segmentei! Também não posso soltá-lo como ele diz "banco de dados de manutenção não pode ser descartado"
Matt Skeldon
@ MattSkeldon, não faço ideia do que essa mensagem significa. No PostgreSQL de baunilha, você pode eliminar qualquer banco de dados, exceto o template0 e o template1. Talvez você use alguma versão não gratuita / comercial? Talvez seja problema do cliente, não do servidor? Você tentou o psql?
Filiprem
Infelizmente, venho de um background SQL, usando o PGSQL está sendo usado devido ao status não comercial / gratuito.
22617 Matt Skeldon
Isso não funciona para mim onde há sessões de zumbi de longa duração. O pg_terminate_backend () não interrompe essas sessões, por isso ainda estou um pouco preocupado com o que fazer: sou um Postgres su, mas não tenho acesso ao servidor em que ele está sendo executado.
285 Alexander Alexander
6
Não é uma maneira de fazer isso com os utilitários de shell dropdb& pg_ctl(ou pg_ctlclusterem Debian e seus derivados). Mas o método do @ filiprem é superior por várias razões:
Apenas desconecta os usuários do banco de dados em questão.
Não é necessário reiniciar o cluster inteiro.
Evita reconexões imediatas, possivelmente estragando o dropdbcomando.
Cito man pg_ctlcluster:
Com a --forceopção, o modo "rápido" é usado, o que reverte todas as transações ativas, desconecta os clientes imediatamente e, portanto, é encerrado de maneira limpa. Se isso não funcionar, o desligamento é tentado novamente no modo "imediato", o que pode deixar o cluster em um estado inconsistente e, portanto, levará a uma recuperação na próxima inicialização. Se isso ainda não ajudar, o processo do postmaster será interrompido. Sai com 0 em caso de sucesso, com 2 se o servidor não estiver em execução e com 1 em outras condições de falha. Este modo deve ser usado apenas quando a máquina estiver prestes a ser desligada.
pg_ctlcluster 9.1 main restart --force
ou
pg_ctl restart -D datadir -m fast
ou
pg_ctl restart -D datadir -m immediate
imediatamente seguido por:
dropdb mydb
Possivelmente em um roteiro para sucessão imediata.
Isso não é apenas ideal, pois retrocede a instância completa do postgres, mas não é garantido que funcione. É possível que um cliente se conecte entre o momento em que você reinicia o servidor e tenta executar o dropdb novamente. A resposta do @filiprem acima desabilita todas as conexões com o banco de dados antes de desconectar e mantém outros bancos de dados ativos.
Jim Mitchener
6
Usando a resposta de @ filiprem no meu caso e simplificando-a:
-- 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
Se você estiver em algo como o RDS, em que conexões sem um banco de dados selecionado o colocam no banco de dados que você pediu para ser criado por padrão, você pode fazer essa variante para evitar que seja a última conexão aberta.
Não é uma maneira de fazer isso com os utilitários de shell
dropdb
&pg_ctl
(oupg_ctlcluster
em Debian e seus derivados). Mas o método do @ filiprem é superior por várias razões:dropdb
comando.Cito
man pg_ctlcluster
:ou
ou
imediatamente seguido por:
Possivelmente em um roteiro para sucessão imediata.
fonte
Usando a resposta de @ filiprem no meu caso e simplificando-a:
fonte
Se você estiver em algo como o RDS, em que conexões sem um banco de dados selecionado o colocam no banco de dados que você pediu para ser criado por padrão, você pode fazer essa variante para evitar que seja a última conexão aberta.
fonte