Resumo / TL;DR
Em 3 passos poderá executar de forma muito simples:
INSERT INTO production_db.table_name
SELECT * FROM backup_db.table_name -- backup_db being remote
Primeiro instale o backup localmente, depois obtenha um script SQL, terceiro abra seu localhost para o mundo exterior com ngrok .
Vamos?
1. Baixe seu arquivo de despejo em Heroku e despeje em algum lugar:
- Você pode fazer isso em um banco de dados remoto se tiver alguns servidores disponíveis. Mas se, como eu, você não quiser provisionar outro banco de dados de produção no Heroku ou em outro lugar, localmente servirá.
- Gosto de usar o PGAdmin
(disponível em Linux, Mac e Windows), mas usando linha de comando e
psql
também fará (lendo isto postar por exemplo) - No PGAdmin, você faria
Create a database
. Em seguida, clique com o botão direito nele e use orestore
função. Selecione seu arquivo de despejo, clique emRestore
e pronto:seus dados de backup estão disponíveis localmente! Bom trabalho!
2. Acesse-o de seu banco de dados remoto
Eu queria fazer o seguinte:
SELECT * FROM backup_db.table_name
-- So I could then do
INSERT INTO production_db.table_name
SELECT * FROM backup_db.table_name
E eu estaria tudo pronto. Super fácil né? Muito obvio? Isso já deve ter sido feito centenas de vezes. Bem não!
Existe um utilitário chamado
db_link
no Postgres 9.1+, mas é bastante restritivo, pois a seguinte sintaxe se aplica:SELECT fname, lname FROM db_link('host=localhost dbname=backup-28-08', 'SELECT fname, lname FROM users') AS remote (varchar255 fname varchar255 lname)
Cada nome de coluna precisa ser repetido duas vezes, incluindo seu tipo. Muito pesado, estamos longe do simples
SELECT * FROM backup_db.table_name
Então a ideia aqui é usar o
information_schema
conteúdo da tabela, que descreve cada tabela com seus nomes de coluna, seus tipos, etc. Encontrei esta pergunta em SO:Especificar lista de definição de coluna dblink de um tipo existente local
o que me ajudou muito (Obrigado bentrm
). Mas sua solução foi um processo de duas etapas, primeiro gerando uma função, depois consultando-a:
SELECT dblink_star_func('dbname=ben', 'public', 'test');
SELECT * FROM star_test() WHERE data = 'success';
E eu ainda estava visando um forro 1. Depois de um pouco de dor (não sendo um SQL Guru), aqui está o Gist:https://gist.github. com/augnustin/d30973ea8b5bf0067841
agora posso fazer:
SELECT * FROM remote_db(NULL::users) -- (Still not 100% about why I need the NULL::)
-- And also
INSERT INTO users
SELECT * FROM remote_db(NULL::users)
Incrível, certo?
3. Acesse localhost remotamente
Se o seu banco de dados remoto já estiver disponível na Internet (=tem um endereço IP, um nome de domínio, por exemplo, para Heroku, será parecido com:
ec2-54-217-229-169.eu-west-1.compute.amazonaws.com:5672/df68cfpbufjd9p
) você pode pular esta etapa . Mas se você usar seu banco de dados local, precisará disponibilizá-lo do mundo exterior (para que o banco de dados Heroku possa acessá-lo). Para isso, uso o maravilhoso ngrok .
Uma vez instalado, só preciso digitar o seguinte comando:
ngrok -proto=tcp 5432 #5432 being the default port for Postgresql. (Adapt if necessary)
Tunnel Status online
Version 1.7/1.6
Forwarding tcp://ngrok.com:51727 -> 127.0.0.1:5432
Web Interface 127.0.0.1:4040
# Conn 0
Avg Conn Time 0.00ms
E você só precisa conectar
db_link
(na essência) para host=ngrock.com port=51727
e você está bom para ir ! 4. Indo além
Há muitas melhorias possíveis para isso. Aqui estão alguns que eu já vi:
- Considerando o script como um recurso padrão para
db_link
função - Ser mais à prova de erros se as estruturas de banco de dados forem diferentes no backup e na produção
- Fazer uma ferramenta de comparação entre os resultados do banco de dados e os resultados do backup (para retornar apenas linhas de comparação)
- Lidar com junções simples
- E ainda mais seria ter um adaptador de nível de aplicativo (por exemplo, ActiveRecord em Rails) que pudesse permitir a manipulação de objetos de back-end em vez de SQL bruto como agora
Espero ter sido claro! Por favor, peça mais detalhes caso contrário