Crear una copia de una base de datos en PostgreSQL

730

¿Cuál es la forma correcta de copiar toda la base de datos (su estructura y datos) a una nueva en pgAdmin?

egaga
fuente

Respuestas:

1121

Postgres permite el uso de cualquier base de datos existente en el servidor como plantilla al crear una nueva base de datos. No estoy seguro de si pgAdmin le da la opción en el cuadro de diálogo crear base de datos, pero debería poder ejecutar lo siguiente en una ventana de consulta si no es así:

CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;

Aún así, puede obtener:

ERROR:  source database "originaldb" is being accessed by other users

Para desconectar a todos los demás usuarios de la base de datos, puede usar esta consulta:

SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity 
WHERE pg_stat_activity.datname = 'originaldb' AND pid <> pg_backend_pid();
Campana
fuente
68
Tenga en cuenta que originaldb debe estar inactivo (sin transacciones de escritura) para que esto funcione.
synecdoche
62
en pgAdmin3, en el panel Explorador de objetos (izquierda), puedo seleccionar Servers-> (mi servidor) -> Databases, hacer clic con el botón derecho en Bases de datos y seleccionar "Nueva base de datos". Una de las opciones es la plantilla, y el SQL utilizado para crear la base de datos es equivalente. Es por lo tanto más rápido que un dump / restore en el mismo servidor.
jwhitlock
22
Sé que este es un viejo Q / A, pero creo que necesita aclaración: cuando @synecdoche dice que originaldb debe estar inactivo, eso significa que no hay posibilidad de escritura. "Copiar" una base de datos de esta manera no bloquea originaldb. PostgreSQL solo impide iniciar la copia si hay otros que acceden a originaldb, no después de que comience la copia, por lo que es posible que otra conexión pueda modificar la base de datos mientras se produce la "copia". En mi humilde opinión, esta puede ser la respuesta más fácil, pero la "mejor" sería usar dump / restore.
Josh
10
Acabo de ver esto. @ Josh: mientras el original db se copia creando una base de datos con plantilla, postgresql no permite crear una nueva conexión, por lo que no es posible realizar cambios.
ceteras
44
Tenga en cuenta que si está utilizando pgAdmin y está ejecutando CREATE DATABASE ... TEMPLATE xxx desde una ventana de comandos SQL, debe desconectarse de la base de datos en la ventana principal de pgAdmin o obtendrá el error sobre los usuarios conectados a la base de datos.
Jack RG
296

Una versión de línea de comandos de la respuesta de Bell :

createdb -O ownername -T originaldb newdb

Esto debe ejecutarse bajo los privilegios del maestro de la base de datos, generalmente postgres.

zbyszek
fuente
55
Este es un buen comando, PERO lo obtendrá createdb: database creation failed: ERROR: source database "conf" is being accessed by other userssi intenta hacerlo en una base de datos de producción y, como se esperaba, no desea cerrarlo para crear una copia.
sorin
77
Sí, las mismas advertencias se aplican a este comando, en cuanto a la invocación explícita de CREATE DATABASE. Como dicen los comentarios para la respuesta de Bell anterior, la base de datos debe estar inactiva.
zbyszek
108

Para clonar una base de datos existente con postgres, puede hacerlo

/* KILL ALL EXISTING CONNECTION FROM ORIGINAL DB (sourcedb)*/
SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity 
WHERE pg_stat_activity.datname = 'SOURCE_DB' AND pid <> pg_backend_pid();

/* CLONE DATABASE TO NEW ONE(TARGET_DB) */
CREATE DATABASE TARGET_DB WITH TEMPLATE SOURCE_DB OWNER USER_DB;

IT matará toda la conexión a la fuente db evitando el error

ERROR:  source database "SOURCE_DB" is being accessed by other users
Brugolo
fuente
77
+1 por mencionar una solución de script para evitar el error de acceso
intimidar el
14
En Postgres 9.2 Tengo que sustituir procpidcon pidpara que esto funcione
marxjohnson
75

En el entorno de producción, donde la base de datos original está bajo tráfico, simplemente estoy usando:

pg_dump production-db | psql test-db
Tregoreg
fuente
8
Un problema que he encontrado con este método es que pg_dump mantendrá abierta su transacción hasta que se complete la restauración en la nueva base de datos, incluso si pg_dump realmente ha terminado su volcado. Esto puede causar problemas de bloqueo en algunos casos (por ejemplo, si se ejecuta una instrucción DDL en el DB de origen).
Chris Butler
3
Más uno para no usar archivos intermedios temporales.
Ardee Aram
También fue mi solución. Ayer funcionó, ahora se violan las restricciones únicas aleatorias. Nota: Dejo caer toda la tabla al receptor db.
gunzapper
1
@AlexanderMills pg_dump -s? postgresql.org/docs/current/static/app-pgdump.html
Tregoreg
1
Esto supone que test-db existe. De lo contrario, cree la nueva base de datos con$ createdb newdb
SamGoody
50

No sé acerca de pgAdmin, pero pgdumple da un volcado de la base de datos en SQL. Solo necesita crear una base de datos con el mismo nombre y hacer

psql mydatabase < my dump

para restaurar todas las tablas y sus datos y todos los privilegios de acceso.

TrayMan
fuente
Gracias, necesitaba crear un volcado desde otro servidor, y parece que esto ayuda: postgresql.org/docs/8.3/interactive/…
egaga
19
Incluso puede hacerlo, pg_dump -U postgres sourcedb | psql -U postgres newdbaunque la eficacia de esta técnica puede ser cuestionable (ya que probablemente termine cambiando de contexto entre lecturas y escrituras)
Frank Farmer
1
Incluso puede obtener su volcado desde una máquina remota a través de ssh: ssh dbserver pg_dump DBNAME | psql NEWDB... o pg_dump DBNAME | ssh otherserver pgsql NEWDB ... Los permisos y la autenticación, por supuesto, deben manejarse de la forma que desee.
ghoti
23

Primero, sudocomo usuario de la base de datos:

sudo su postgres

Vaya a la línea de comando PostgreSQL:

psql

Cree la nueva base de datos, otorgue los derechos y salga:

CREATE DATABASE new_database_name;
GRANT ALL PRIVILEGES ON DATABASE new_database_name TO my_user;
\d

Copie la estructura y los datos de la base de datos anterior a la nueva:

pg_dump old_database_name | psql new_database_name
Mathieu Rodic
fuente
¿Cómo asegurarse de que todo esté bien incluso que ocurrieron algunos errores (problema de red)? ¿Cómo verificar si las dos bases de datos son las mismas después de la migración?
BAE
Los errores deben mostrarse en la terminal siempre que se encuentren. Las dos bases de datos deben ser las mismas después de la operación. Sin embargo, no sé cómo verificar esto ...
Mathieu Rodic
2
Funciona de maravilla, lo hice mientras la base de datos estaba en producción.
BioRod
Esto parece funcionar bien; sin embargo, las dos bases de datos tienen un tamaño de disco diferente a través de \l+. ¿Por qué la diferencia de tamaño?
kosgeinsky
@kosgeinsky esto ha sido ampliamente respondido aquí: dba.stackexchange.com/a/102089/39386
Mathieu Rodic
18

Uní este enfoque junto con los ejemplos de arriba. Estoy trabajando en un servidor "bajo carga" y recibí el error cuando intenté el enfoque de @zbyszek. También buscaba una solución de "solo línea de comando".

createdb: database creation failed: ERROR: source database "exampledb" is being accessed by other users.

Esto es lo que funcionó para mí ( Comandos incluidos antes nohuppara mover la salida a un archivo y protegerlo de la desconexión de un servidor ):

  1. nohup pg_dump exampledb > example-01.sql
  2. createdb -O postgres exampledbclone_01

    mi usuario es "postgres"

  3. nohup psql exampledbclone_01 < example-01.sql

fusion27
fuente
15

En pgAdmin puede hacer una copia de seguridad desde su base de datos original, y luego simplemente crear una nueva base de datos y restaurar desde la copia de seguridad recién creada:

  1. Haga clic derecho en la base de datos de origen, Copia de seguridad ... y volcar en un archivo.
  2. Haga clic derecho, Nuevo objeto, Nueva base de datos ... y nombre el destino.
  3. Haga clic derecho en la nueva base de datos, Restaurar ... y seleccione su archivo.
Isomorfo
fuente
Tengo tablas relacionadas a través de claves externas y esto funcionó bien.
Randall Blake
12

¿Cuál es la forma correcta de copiar toda la base de datos (su estructura y datos) a una nueva en pgAdmin?

Responder:

CREATE DATABASE newdb WITH TEMPLATE originaldb;

Tratado y probado.

Anirban Chakrabarti
fuente
3
Esto requiere que originaldb no esté en uso. El método de Isomorph no.
Bradley
2
La misma respuesta se proporcionó casi tres años antes que la suya
Jason S
8

De la documentación , no se recomienda usar createdbo CREATE DATABASEcon plantillas:

Aunque es posible copiar una base de datos que no sea template1 especificando su nombre como plantilla, esto (todavía) no pretende ser una función de "BASE DE DATOS DE COPIA" de uso general. La principal limitación es que no se pueden conectar otras sesiones a la base de datos de la plantilla mientras se está copiando. CREATE DATABASE fallará si existe alguna otra conexión cuando se inicia; de lo contrario, las nuevas conexiones a la base de datos de plantilla se bloquean hasta que se completa CREATE DATABASE

pg_dump o pg_dumpall es una buena manera de copiar la base de datos Y TODOS LOS DATOS. Si está utilizando una GUI como pgAdmin, estos comandos se invocan detrás de escena cuando ejecuta un comando de respaldo. La copia a una nueva base de datos se realiza en dos fases: copia de seguridad y restauración

pg_dumpallguarda todas las bases de datos en el clúster PostgreSQL. La desventaja de este enfoque es que terminas con un archivo de texto potencialmente muy grande lleno de SQL requerido para crear la base de datos y completar los datos. La ventaja de este enfoque es que obtiene todos los roles (permisos) para el clúster de forma gratuita. Para volcar todas las bases de datos, haga esto desde la cuenta de superusuario

pg_dumpall > db.out

y para restaurar

psql -f db.out postgres

pg_dumptiene algunas opciones de compresión que te dan archivos mucho más pequeños. Tengo una base de datos de producción que respaldo dos veces al día con un trabajo cron usando

pg_dump --create --format=custom --compress=5 --file=db.dump mydatabase

donde compressestá el nivel de compresión (0 a 9) y createle dice pg_dumpque agregue comandos para crear la base de datos. Restaurar (o mover al nuevo clúster) usando

pg_restore -d newdb db.dump

donde newdb es el nombre de la base de datos que desea usar.

Otras cosas para pensar

PostgreSQL usa ROLES para administrar los permisos. Estos no son copiados por pg_dump. Además, no hemos tratado la configuración en postgresql.conf y pg_hba.conf (si está moviendo la base de datos a otro servidor). Tendrás que descubrir la configuración de conf por tu cuenta. Pero hay un truco que acabo de descubrir para respaldar roles. Los roles se administran a nivel de clúster y puede solicitar pg_dumpalluna copia de seguridad solo de los roles con el --roles-onlyinterruptor de línea de comando.

bfris
fuente
7

PostgreSQL 9.1.2:

$ CREATEDB new_db_name -T orig_db_name -O db_user;
Arta
fuente
3
Probablemente, esto se implementa como CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;un resultado y requiere que la base de datos original esté inactiva (sin conexiones con acceso de escritura) y que se eviten las conexiones nuevas a la base de datos original mientras la copia está en proceso. Si estás contento con eso, esto funciona.
Mikko Rantalainen
Bonito detalle. ¡Gracias!
Arta
6

Para aquellos que todavía están interesados, he creado un script bash que hace (más o menos) lo que el autor quería. Tuve que hacer una copia diaria de la base de datos de negocios en un sistema de producción, este script parece hacer el truco. Recuerde cambiar el nombre de la base de datos / usuario / valores pw.

#!/bin/bash

if [ 1 -ne $# ]
then
  echo "Usage `basename $0` {tar.gz database file}"
  exit 65;
fi

if [ -f "$1" ]
then
  EXTRACTED=`tar -xzvf $1`
  echo "using database archive: $EXTRACTED";
else
  echo "file $1 does not exist"
  exit 1
fi


PGUSER=dbuser
PGPASSWORD=dbpw
export PGUSER PGPASSWORD

datestr=`date +%Y%m%d`


dbname="dbcpy_$datestr"
createdbcmd="CREATE DATABASE $dbname WITH OWNER = postgres ENCODING = 'UTF8' TABLESPACE = pg_default LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8' CONNECTION LIMIT = -1;"
dropdbcmp="DROP DATABASE $dbname"

echo "creating database $dbname"
psql -c "$createdbcmd"

rc=$?
if [[ $rc != 0 ]] ; then
  rm -rf "$EXTRACTED"
  echo "error occured while creating database $dbname ($rc)"
  exit $rc
fi


echo "loading data into database"
psql $dbname < $EXTRACTED > /dev/null

rc=$?

rm -rf "$EXTRACTED"

if [[ $rc != 0 ]] ; then
  psql -c "$dropdbcmd"
  echo "error occured while loading data to database $dbname ($rc)"
  exit $rc
fi


echo "finished OK"
Dariusz
fuente
5

Para crear un volcado de base de datos

cd /var/lib/pgsql/
pg_dump database_name> database_name.out

Para volver a volcar la base de datos

psql -d template1
CREATE DATABASE database_name WITH  ENCODING 'UTF8' LC_CTYPE 'en_US.UTF-8' LC_COLLATE 'en_US.UTF-8' TEMPLATE template0;
CREATE USER  role_name WITH PASSWORD 'password';
ALTER DATABASE database_name OWNER TO role_name;
ALTER USER role_name CREATEDB;
GRANT ALL PRIVILEGES ON DATABASE database_name to role_name;


CTR+D(logout from pgsql console)
cd /var/lib/pgsql/

psql -d database_name -f database_name.out
Jagdish Narayandasani
fuente
5

Aquí está todo el proceso de crear una copia sobre una base de datos utilizando solo la GUI pgadmin4 (a través de copia de seguridad y restauración)

Postgres viene con Pgadmin4. Si usa macOS, puede presionar CMD+ SPACEy escribir pgadmin4para ejecutarlo. Esto abrirá una pestaña del navegador en Chrome.


Pasos para copiar

1. Crear la copia de seguridad

Haga esto haciendo clic derecho en la base de datos -> "copia de seguridad"

ingrese la descripción de la imagen aquí

2. Déle un nombre al archivo.

Al igual test12345. Haga clic en copia de seguridad. Esto crea un volcado de archivo binario, no está en un .sqlformato

ingrese la descripción de la imagen aquí

3. Vea dónde se descargó

Debería haber una ventana emergente en la parte inferior derecha de la pantalla. Haga clic en la página "más detalles" para ver dónde se descargó su copia de seguridad

ingrese la descripción de la imagen aquí

4. Encuentre la ubicación del archivo descargado

En este caso, es /users/vincenttang

ingrese la descripción de la imagen aquí

5. Restaurar la copia de seguridad de pgadmin

Suponiendo que realizó los pasos 1 a 4 correctamente, tendrá un archivo binario de restauración. Puede llegar un momento en que su compañero de trabajo quiera usar su archivo de restauración en su máquina local. Que dicha persona vaya a pgadmin y restaure

Haga esto haciendo clic derecho en la base de datos -> "restaurar"

ingrese la descripción de la imagen aquí

6. Seleccione el buscador de archivos

Asegúrese de seleccionar la ubicación del archivo manualmente, NO arrastre y suelte un archivo en los campos del cargador en pgadmin. Porque te encontrarás con permisos de error. En su lugar, busque el archivo que acaba de crear:

ingrese la descripción de la imagen aquí

7. Encuentra dicho archivo

Puede que tenga que cambiar el filtro en la parte inferior derecha a "Todos los archivos". Busque el archivo a partir de ese momento, desde el paso 4. Ahora presione el botón "Seleccionar" en la esquina inferior derecha para confirmar

ingrese la descripción de la imagen aquí

8. Restaurar dicho archivo

Verá esta página nuevamente, con la ubicación del archivo seleccionado. Sigue adelante y restauralo

ingrese la descripción de la imagen aquí

9. Éxito

Si todo está bien, la parte inferior derecha debería mostrar un indicador que muestra una restauración exitosa. Puede navegar a sus tablas para ver si los datos se han restaurado correctamente en cada tabla.

10. Si no tuvo éxito:

Si el paso 9 falla, intente eliminar su antiguo esquema público en su base de datos. Vaya a "Herramienta de consulta"

ingrese la descripción de la imagen aquí

Ejecute este bloque de código:

DROP SCHEMA public CASCADE; CREATE SCHEMA public;

ingrese la descripción de la imagen aquí

Ahora intente los pasos 5 a 9 nuevamente, debería funcionar

EDITAR - Algunas notas adicionales. Actualice PGADMIN4 si obtiene un error durante la carga con algo similar a "versión no compatible del encabezado 1.14 del archivador" durante la restauración

Vincent Tang
fuente
3

Si la base de datos tiene conexiones abiertas, este script puede ayudar. Lo uso para crear una base de datos de prueba a partir de una copia de seguridad de la base de datos de producción en vivo todas las noches. Esto supone que tiene un archivo de copia de seguridad .SQL de la base de datos de producción (lo hago dentro de webmin).

#!/bin/sh

dbname="desired_db_name_of_test_enviroment"
username="user_name"
fname="/path to /ExistingBackupFileOfLive.sql"

dropdbcmp="DROP DATABASE $dbname"
createdbcmd="CREATE DATABASE $dbname WITH OWNER = $username "

export PGPASSWORD=MyPassword



echo "**********"
echo "** Dropping $dbname"
psql -d postgres -h localhost -U "$username" -c "$dropdbcmp"

echo "**********"
echo "** Creating database $dbname"
psql -d postgres -h localhost -U "$username" -c "$createdbcmd"

echo "**********"
echo "** Loading data into database"
psql -d postgres -h localhost -U "$username" -d "$dbname" -a -f "$fname"
grito
fuente
1

Con pgAdmin, desconecte la base de datos que desea usar como plantilla. Luego lo selecciona como plantilla para crear la nueva base de datos, esto evita obtener el error ya en uso.

árbol de hoja perenne2
fuente
0

Si desea copiar todo el esquema, puede hacer un pg_dump con el siguiente comando:

pg_dump -h database.host.com -d database_name -n schema_name -U database_user --password

Y cuando desee importar ese volcado, puede usar:

psql "host=database.host.com user=database_user password=database_password dbname=database_name options=--search_path=schema_name" -f sql_dump_to_import.sql

Más información sobre las cadenas de conexión: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING

O simplemente combinándolo en un revestimiento:

pg_dump -h database.host.com -d postgres -n schema_name -U database_user --password | psql "host=database.host.com user=database_user password=database_password dbname=database_name options=--search_path=schema_name”
Maksim Luzik
fuente
0
  1. Abra la ventana principal en pgAdmin y luego abra otra ventana de herramientas de consulta
  2. En las ventanas principales en pgAdmin,

Desconecte la base de datos "con plantilla" que desea usar como plantilla.

  1. Ir a la ventana de herramientas de consulta

Ejecute 2 consultas como a continuación

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

(La instrucción SQL anterior terminará todas las sesiones activas con TemplateDB y ahora puede seleccionarla como plantilla para crear la nueva base de datos TargetDB, esto evita obtener el error ya en uso).

CREATE DATABASE 'TargetDB'
  WITH TEMPLATE='TemplateDB'
       CONNECTION LIMIT=-1;
titushui
fuente
-4

Prueba esto:

CREATE DATABASE newdb WITH ENCODING='UTF8' OWNER=owner TEMPLATE=templatedb LC_COLLATE='en_US.UTF-8' LC_CTYPE='en_US.UTF-8' CONNECTION LIMIT=-1;

gl XD

usuario3108031
fuente