Forzar caída db mientras otros pueden estar conectados
104
Necesito eliminar una base de datos de un clúster de base de datos PostgreSQL. ¿Cómo puedo hacerlo incluso si hay conexiones activas? Necesito una especie de -forcebandera, que eliminará todas las conexiones y luego la base de datos.
¿Cómo puedo implementarlo?
Estoy usando dropdbactualmente, pero otras herramientas son posibles.
En PostgreSQL * , no puede descartar una base de datos mientras los clientes están conectados a ella.
Al menos, no con la dropdbutilidad, que es solo una simple envoltura alrededor de DROP DATABASEla consulta del servidor.
Una solución bastante sólida sigue:
Conéctese a su servidor como superusuario , utilizando psqlu otro cliente. No , no utilizar la base de datos que desea desconectar.
psql -h localhost postgres postgres
Ahora, utilizando el cliente de base de datos simple, puede forzar la caída de la base de datos mediante tres pasos simples:
Asegúrese de que nadie pueda conectarse a esta base de datos. Puede usar uno de los siguientes métodos (el segundo parece más seguro, pero no impide las conexiones de los superusuarios).
/* 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; */
Forzar la desconexión de todos los clientes conectados a esta base de datos, utilizando pg_terminate_backend.
SELECT pg_terminate_backend(pid)FROM pg_stat_activity
WHERE 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'; */
Descarte la base de datos.
DROPDATABASE mydb;
El paso 1 requiere privilegios de superusuario para el primer método y privilegios de propietario de la base de datos para el segundo. El paso 2 requiere privilegios de superusuario . El paso 3 requiere privilegio de propietario de la base de datos .
* Esto se aplica a todas las versiones de PostgreSQL, hasta la versión 11.
Así que no sé qué hice mal, ¡pero ahora ni siquiera puedo conectarme a la base de datos a la que apunté! Tampoco puedo soltarlo, ya que dice "La base de datos de mantenimiento no se puede soltar"
Matt Skeldon
@MattSkeldon, no tengo idea de lo que significa este mensaje. En Vanilla PostgreSQL puede eliminar cualquier base de datos, excepto template0 y template1. ¿Quizás usas alguna versión no gratuita / comercial? ¿Quizás es un problema del cliente, no un problema del servidor? ¿Intentaste con psql?
filiprem
Lamentablemente vengo de un fondo SQL, el uso de PGSQL se está utilizando debido al estado no comercial / libre.
Matt Skeldon
Esto no funciona para mí donde hay sesiones de zombies de larga duración. pg_terminate_backend () no mata esas sesiones, así que todavía estoy un poco atascado sobre qué hacer: soy un Postgres su, pero no tengo acceso al servidor en el que se está ejecutando.
Alexander
6
No es una forma de hacer esto con las utilidades de shell dropdby pg_ctl(o pg_ctlclusteren Debian y derivados). Pero el método de @filiprem es superior por varias razones:
Solo desconecta a los usuarios de la base de datos en cuestión.
No necesita reiniciar todo el clúster.
Impide reconexiones inmediatas, posiblemente estropeando el dropdbcomando.
Cito man pg_ctlcluster:
Con la --forceopción, se utiliza el modo "rápido" que revierte todas las transacciones activas, desconecta a los clientes de inmediato y, por lo tanto, se apaga limpiamente. Si eso no funciona, el apagado se intenta nuevamente en modo "inmediato", lo que puede dejar el clúster en un estado inconsistente y, por lo tanto, conducirá a una ejecución de recuperación en el próximo inicio. Si esto todavía no ayuda, el proceso de administrador de correo se cancela. Sale con 0 en caso de éxito, con 2 si el servidor no se está ejecutando y con 1 en otras condiciones de falla. Este modo solo debe usarse cuando la máquina está a punto de apagarse.
pg_ctlcluster 9.1 main restart --force
o
pg_ctl restart -D datadir -m fast
o
pg_ctl restart -D datadir -m immediate
seguido inmediatamente por:
dropdb mydb
Posiblemente en un guión para la sucesión inmediata.
Esto no solo es menos que ideal, ya que patea la instancia completa de postgres sino que no se garantiza que funcione. Es posible que un cliente se conecte entre el momento en que reinicia el servidor e intenta ejecutar dropdb nuevamente. La respuesta anterior de @filiprem deshabilita todas las conexiones a la base de datos antes de desconectarse y mantendrá otras bases de datos activas.
Jim Mitchener
6
Usando la respuesta de @filiprem en mi caso y simplificándola:
-- 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
Si está en algo como RDS donde las conexiones sin una base de datos seleccionada lo colocan en la base de datos que solicitó que se cree por defecto, puede hacer esta variante para evitar ser la última conexión abierta.
No es una forma de hacer esto con las utilidades de shell
dropdb
ypg_ctl
(opg_ctlcluster
en Debian y derivados). Pero el método de @filiprem es superior por varias razones:dropdb
comando.Cito
man pg_ctlcluster
:o
o
seguido inmediatamente por:
Posiblemente en un guión para la sucesión inmediata.
fuente
Usando la respuesta de @filiprem en mi caso y simplificándola:
fuente
Si está en algo como RDS donde las conexiones sin una base de datos seleccionada lo colocan en la base de datos que solicitó que se cree por defecto, puede hacer esta variante para evitar ser la última conexión abierta.
fuente