Criando uma cópia de um banco de dados no PostgreSQL

730

Qual é a maneira correta de copiar um banco de dados inteiro (sua estrutura e dados) para um novo no pgAdmin?

egaga
fonte

Respostas:

1121

O Postgres permite o uso de qualquer banco de dados existente no servidor como modelo ao criar um novo banco de dados. Não tenho certeza se o pgAdmin oferece a opção na caixa de diálogo criar banco de dados, mas você poderá executar o seguinte em uma janela de consulta, se isso não acontecer:

CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;

Ainda assim, você pode obter:

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

Para desconectar todos os outros usuários do banco de dados, você pode 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();
Sino
fonte
68
Observe que o originaldb precisa estar ocioso (sem transações de gravação) para que isso funcione.
Synecdoche
62
no pgAdmin3, no painel Navegador de objetos (esquerda), posso selecionar Servers-> (meu servidor) -> Databases, clicar com o botão direito do mouse em Bancos de dados e selecionar "Novo banco de dados". Uma das opções é o modelo, e o SQL usado para criar o banco de dados é equivalente. É por isso muito mais rápido do que um dump / restore no mesmo servidor.
jwhitlock
22
Sei que este é um Q / A antigo, mas acho que precisa de esclarecimentos: quando o @synecdoche diz que o originaldb deve estar ocioso, isso significa que não há possibilidade de gravação. "Copiar" um banco de dados dessa maneira não bloqueia o originaldb. O PostgreSQL apenas impede o início da cópia se houver outras pessoas acessando o originaldb - não após o início da cópia, portanto, é possível que outra conexão possa modificar o banco de dados enquanto a "cópia" está ocorrendo. IMHO, esta pode ser a resposta mais fácil, mas o "melhor" seria usar o dump / restore.
27412 Josh
10
Acabei de ver isso. @ Josh: enquanto o originaldb está sendo copiado pela criação de banco de dados com modelo, o postgresql não permite criar uma nova conexão a ele, portanto, nenhuma alteração é possível.
ceteras
4
Observe que se você estiver usando o pgAdmin e executando CREATE DATABASE ... TEMPLATE xxx a partir de uma janela de comando SQL, deverá desconectar-se do banco de dados na janela principal do pgAdmin ou obterá o erro sobre os usuários conectados ao banco de dados.
Jack RG
296

Uma versão em linha de comando da resposta de Bell :

createdb -O ownername -T originaldb newdb

Isso deve ser executado sob os privilégios do mestre do banco de dados, geralmente o postgres.

zbyszek
fonte
5
Este é um bom comando, mas você receberá createdb: database creation failed: ERROR: source database "conf" is being accessed by other usersse tentar fazê-lo em um banco de dados de produção e, como esperado, não deseja desativá-lo para criar uma cópia.
Sorin
7
Sim, as mesmas advertências se aplicam a este comando, como na chamada explícita CREATE DATABASE. Como dizem os comentários da resposta de Bell acima, o banco de dados deve estar ocioso.
precisa saber é o seguinte
108

Para clonar um banco de dados existente com o postgres, você pode fazer isso

/* 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;

TI matará toda a conexão com o banco de dados de origem, evitando o erro

ERROR:  source database "SOURCE_DB" is being accessed by other users
Brugolo
fonte
7
1 para mencionar uma solução de script para evitar o erro de acesso
valentão
14
Em Postgres 9.2 têm de ser substituídas procpidcom pidpara que isso funcione
marxjohnson
75

No ambiente de produção, onde o banco de dados original está sob tráfego, estou simplesmente usando:

pg_dump production-db | psql test-db
Tregoreg
fonte
8
Um problema que encontrei com esse método é que o pg_dump manterá aberta sua transação até que a restauração no novo banco de dados seja concluída, mesmo que o pg_dump tenha realmente concluído seu despejo. Isso pode causar problemas de bloqueio em alguns casos (por exemplo, se uma instrução DDL for executada no banco de dados de origem).
Chris Butler
3
Mais um por não usar arquivos intermediários temporários.
Ardee Aram
Também foi minha solução. Ontem funcionou, agora restrições únicas aleatórias são violadas. Nota: Largo toda a tabela no receptor db.
gunzapper
1
@AlexanderMills pg_dump -s? postgresql.org/docs/current/static/app-pgdump.html
Tregoreg
1
Isso pressupõe que o test-db exista. Caso contrário, crie o novo banco de dados com$ createdb newdb
SamGoody
50

Não conhece o pgAdmin, mas pgdumpfornece um despejo do banco de dados no SQL. Você só precisa criar um banco de dados com o mesmo nome e fazer

psql mydatabase < my dump

restaurar todas as tabelas e seus dados e todos os privilégios de acesso.

TrayMan
fonte
Obrigado, eu precisava criar um despejo de outro servidor, e parece que isso ajuda: postgresql.org/docs/8.3/interactive/…
egaga
19
Você mesmo pode fazer pg_dump -U postgres sourcedb | psql -U postgres newdb, embora a eficiência desta técnica pode ser questionável (desde que você provavelmente acabar troca de contexto entre leituras e gravações)
Frank fazendeiro
1
Você pode até obter seu dump de uma máquina remota via ssh: ssh dbserver pg_dump DBNAME | psql NEWDB... ou pg_dump DBNAME | ssh otherserver pgsql NEWDB ... É claro que as permissões e a autenticação precisam ser tratadas da maneira que você quiser.
ghoti
23

Primeiro, sudocomo usuário do banco de dados:

sudo su postgres

Vá para a linha de comando do PostgreSQL:

psql

Crie o novo banco de dados, dê os direitos e saia:

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

Copie a estrutura e os dados do banco de dados antigo para o novo:

pg_dump old_database_name | psql new_database_name
Mathieu Rodic
fonte
como ter certeza de que tudo está correto, mesmo que ocorram alguns erros (problema de rede)? Como verificar se os dois bancos de dados são iguais após a migração?
BAE 14/01
Os erros devem ser exibidos no terminal sempre que forem encontrados. Os dois bancos de dados devem ser os mesmos após a operação. No entanto, eu não sei como verificar isso ...
Mathieu Rodic
2
Funciona como um encanto, eu fiz enquanto o banco de dados estava em produção.
BioRod
Isso parece funcionar bem; no entanto, os dois bancos de dados têm diferentes tamanhos de disco via \l+. Por que a diferença de tamanho?
22419 kosgeinsky
@kosgeinsky este tem sido amplamente respondidas aqui: dba.stackexchange.com/a/102089/39386
Mathieu Rodic
18

Eu montei essa abordagem junto com os exemplos acima. Estou trabalhando em um servidor "sob carga" e recebi o erro quando tentei a abordagem do @zbyszek. Eu também estava atrás de uma solução "somente linha de comando".

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

Aqui está o que funcionou para mim (os comandos anexados nohuppara mover a saída para um arquivo e proteger contra uma desconexão do servidor ):

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

    meu usuário é "postgres"

  3. nohup psql exampledbclone_01 < example-01.sql

fusion27
fonte
15

No pgAdmin, você pode fazer um backup do seu banco de dados original e criar um novo banco de dados e restaurar a partir do backup que acabou de criar:

  1. Clique com o botão direito do mouse no banco de dados de origem, Backup ... e despeje em um arquivo.
  2. Clique com o botão direito do mouse em Novo objeto, Novo banco de dados ... e atribua um nome ao destino.
  3. Clique com o botão direito do mouse no novo banco de dados, Restaurar ... e selecione seu arquivo.
Isomorfo
fonte
Eu tenho tabelas relacionadas através de chaves estrangeiras e isso funcionou muito bem.
Randall Blake
12

Qual é a maneira correta de copiar um banco de dados inteiro (sua estrutura e dados) para um novo no pgAdmin?

Responda:

CREATE DATABASE newdb WITH TEMPLATE originaldb;

Julgado e testado.

Anirban Chakrabarti
fonte
3
Isso requer que o originaldb não esteja em uso. O método de Isomorph não.
Bradley
2
A mesma resposta foi fornecida quase três anos antes da sua
Jason S
8

Na documentação , não é recomendável usar createdbou CREATE DATABASEcom modelos:

Embora seja possível copiar um banco de dados que não seja o modelo1, especificando seu nome como modelo, este ainda não é um recurso de "COPY DATABASE" de uso geral. A principal limitação é que nenhuma outra sessão pode ser conectada ao banco de dados de modelos enquanto ele está sendo copiado. CREATE DATABASE falhará se houver outra conexão ao iniciar; caso contrário, novas conexões com o banco de dados de modelos serão bloqueadas até que CREATE DATABASE seja concluído.

pg_dumpou pg_dumpallé uma boa maneira de copiar o banco de dados E TODOS OS DADOS. Se você estiver usando uma GUI como pgAdmin, esses comandos serão chamados nos bastidores quando você executar um comando de backup. A cópia para um novo banco de dados é feita em duas fases: Backup e Restauração

pg_dumpallsalva todos os bancos de dados no cluster PostgreSQL. A desvantagem dessa abordagem é que você acaba com um arquivo de texto potencialmente muito grande, cheio de SQL, necessário para criar o banco de dados e preencher os dados. A vantagem dessa abordagem é que você obtém todas as funções (permissões) do cluster gratuitamente. Para despejar todos os bancos de dados, faça isso da conta do superusuário

pg_dumpall > db.out

e restaurar

psql -f db.out postgres

pg_dumppossui algumas opções de compactação que oferecem arquivos muito menores. Eu tenho um banco de dados de produção, faço backup duas vezes por dia com um trabalho cron usando

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

onde compressé o nível de compactação (0 a 9) e creatediz pg_dumppara adicionar comandos para criar o banco de dados. Restaure (ou vá para o novo cluster) usando

pg_restore -d newdb db.dump

onde newdb é o nome do banco de dados que você deseja usar.

Outras coisas em que pensar

O PostgreSQL usa ROLES para gerenciar permissões. Estes não são copiados por pg_dump. Além disso, não lidamos com as configurações no postgresql.conf e no pg_hba.conf (se você estiver movendo o banco de dados para outro servidor). Você terá que descobrir as configurações de conf por conta própria. Mas há um truque que acabei de descobrir para fazer backup de papéis. As funções são gerenciadas no nível do cluster e você pode solicitar o pg_dumpallbackup apenas das funções com a --roles-onlyopção de linha de comando.

bfris
fonte
7

PostgreSQL 9.1.2:

$ CREATEDB new_db_name -T orig_db_name -O db_user;
Arta
fonte
3
Provavelmente, isso é implementado, CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;pois exige que o banco de dados original fique ocioso (sem conexões com acesso de gravação) e que novas conexões com o banco de dados original sejam impedidas enquanto a cópia estiver em andamento. Se você está feliz com isso, isso funciona.
Mikko Rantalainen 6/03/2013
Belo detalhe. Obrigado!
Arta
6

Para aqueles que ainda estão interessados, criei um script bash que faz (mais ou menos) o que o autor queria. Eu tive que fazer uma cópia diária do banco de dados de negócios em um sistema de produção, esse script parece fazer o truque. Lembre-se de alterar os valores do nome do banco de dados / usuário / 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
fonte
5

Para criar despejo de banco de dados

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

Para redefinir o despejo de banco de dados

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
fonte
5

Aqui está todo o processo de criação de uma cópia em um banco de dados usando apenas a GUI do pgadmin4 (via backup e restauração)

O Postgres vem com o Pgadmin4. Se você usa o macOS, pode pressionar CMD+ SPACEe digitar pgadmin4para executá-lo. Isso abrirá uma guia do navegador no chrome.


Etapas para copiar

1. Crie o backup

Faça isso clicando com o botão direito do mouse no banco de dados -> "backup"

insira a descrição da imagem aqui

2. Dê um nome ao arquivo.

Like test12345. Clique em backup. Isso cria um despejo de arquivo binário, não está em um .sqlformato

insira a descrição da imagem aqui

3. Veja onde ele baixou

Deve haver um pop-up na parte inferior direita da tela. Clique na página "mais detalhes" para ver para onde o seu backup foi baixado

insira a descrição da imagem aqui

4. Encontre o local do arquivo baixado

Nesse caso, é /users/vincenttang

insira a descrição da imagem aqui

5. Restaure o backup do pgadmin

Supondo que você executou as etapas 1 a 4 corretamente, você terá um arquivo binário de restauração. Pode chegar um momento em que seu colega de trabalho deseje usar o arquivo de restauração na máquina local. Essa pessoa foi para o pgadmin e restaurou

Faça isso clicando com o botão direito do mouse no banco de dados -> "restore"

insira a descrição da imagem aqui

6. Selecione o localizador de arquivos

Certifique-se de selecionar o local do arquivo manualmente, NÃO arraste e solte um arquivo nos campos do remetente no pgadmin. Porque você terá permissões de erro. Em vez disso, encontre o arquivo que você acabou de criar:

insira a descrição da imagem aqui

7. Encontre o arquivo

Pode ser necessário alterar o filtro na parte inferior direita para "Todos os arquivos". Localize o arquivo depois, a partir da etapa 4. Agora pressione o botão "Selecionar" abaixo para confirmar

insira a descrição da imagem aqui

8. Restaure o arquivo

Você verá esta página novamente, com o local do arquivo selecionado. Vá em frente e restaure

insira a descrição da imagem aqui

9. Sucesso

Se tudo estiver bom, o canto inferior direito deve exibir um indicador mostrando uma restauração bem-sucedida. Você pode navegar até suas tabelas para ver se os dados foram restaurados em cada tabela.

10. Se não foi bem sucedido:

Se a etapa 9 falhar, tente excluir o esquema público antigo no banco de dados. Vá para "Ferramenta de consulta"

insira a descrição da imagem aqui

Execute este bloco de código:

DROP SCHEMA public CASCADE; CREATE SCHEMA public;

insira a descrição da imagem aqui

Agora tente as etapas 5 a 9 novamente, deve funcionar

EDIT - Algumas notas adicionais. Atualize o PGADMIN4 se você estiver recebendo um erro durante o upload com algo parecido com "versão não suportada do cabeçalho do arquivador 1.14" durante a restauração

Vincent Tang
fonte
3

Se o banco de dados tiver conexões abertas, esse script poderá ajudar. Eu uso isso para criar um banco de dados de teste a partir de um backup do banco de dados de produção ao vivo todas as noites. Isso pressupõe que você tenha um arquivo de backup .SQL do banco de dados de produção (eu faço isso no 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"
Screig
fonte
1

Usando o pgAdmin, desconecte o banco de dados que você deseja usar como modelo. Em seguida, você o seleciona como modelo para criar o novo banco de dados, evitando o erro já em uso.

evergreener2
fonte
0

Se você deseja copiar o esquema inteiro, pode fazer um pg_dump com o seguinte comando:

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

E quando você deseja importar esse despejo, pode 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

Mais informações sobre cadeias de conexão: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING

Ou então, basta combiná-lo em um forro:

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
fonte
0
  1. Abra a janela principal no pgAdmin e abra outra janela das ferramentas de consulta
  2. Nas janelas principais do pgAdmin,

Desconecte o banco de dados "modelo" que você deseja usar como modelo.

  1. Ir para a janela Ferramentas de consulta

Execute 2 consultas como abaixo

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

(A instrução SQL acima encerrará todas as sessões ativas com o TemplateDB e agora você poderá selecioná-la como o modelo para criar o novo banco de dados TargetDB, evitando assim o erro já em uso.

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

Tente o seguinte:

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

user3108031
fonte