Sammanfattning / TL;DR
I 3 steg kommer du att kunna utföra mycket enkelt:
INSERT INTO production_db.table_name
SELECT * FROM backup_db.table_name -- backup_db being remote
Installera först säkerhetskopian lokalt, för det andra skaffa ett SQL-skript, för det tredje öppna din lokala värd mot omvärlden med ngrok .
Låt oss gå?
1. Ladda ner din dumpfil på Heroku och dumpa den någonstans:
- Du kan göra det på en fjärrdatabas om du har några servrar tillgängliga. Men om du, som jag, inte vill tillhandahålla en annan produktionsdatabas på Heroku eller någon annanstans, så kommer det att göra det lokalt.
- Jag gillar att använda PGAdmin
(tillgängligt på Linux, Mac och Windows), men med kommandoraden och
psql
kommer också att göra (genom att läsa detta inlägg genom exempel) - I PGAdmin skulle du
Create a database
. Högerklicka sedan på den och användrestore
fungera. Välj din dumpfil, klicka påRestore
och du är klar :din säkerhetskopia är tillgänglig lokalt! Bra jobbat!
2. Få åtkomst till den från din fjärrdatabas
Jag ville göra följande:
SELECT * FROM backup_db.table_name
-- So I could then do
INSERT INTO production_db.table_name
SELECT * FROM backup_db.table_name
Och jag skulle vara klar. Superenkelt, eller hur? Ganska uppenbart? Detta måste redan ha gjorts hundratals gånger. Tja, nej!
Det finns ett verktyg som heter db_link
i Postgres 9.1+, men det är ganska begränsande eftersom följande syntax gäller:
SELECT fname, lname FROM db_link('host=localhost dbname=backup-28-08', 'SELECT fname, lname FROM users') AS remote (varchar255 fname varchar255 lname)
Varje kolumnnamn måste upprepas två gånger inklusive dess typ. Ganska tunga, vi är långt ifrån den enkla SELECT * FROM backup_db.table_name
Så tanken här är att använda information_schema
tabellinnehåll, som beskriver varje tabell med dess kolumnnamn, dess typer etc. Jag hittade den här frågan på SO:Ange dblink kolumndefinitionslista från en lokal befintlig typ
vilket hjälpte mig mycket (Tack bentrm
).
Men dess lösning var en process i två steg, först genererade en funktion och sedan frågade den:
SELECT dblink_star_func('dbname=ben', 'public', 'test');
SELECT * FROM star_test() WHERE data = 'success';
Och jag siktade fortfarande på en 1 liner. Efter lite smärta (som inte är en SQL-guru), här är kärnan:https://gist.github. com/augnustin/d30973ea8b5bf0067841
Jag kan nu göra:
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)
Fantastiskt, eller hur?
3. Få åtkomst till localhost på distans
Om din fjärrdatabas redan är tillgänglig från internet (=har en IP-adress, ett domännamn, t.ex. för Heroku, kommer det att se ut så här:ec2-54-217-229-169.eu-west-1.compute.amazonaws.com:5672/df68cfpbufjd9p
) du kan hoppa över det här steget . Men om du använder din lokala databas måste du göra den tillgänglig från omvärlden (så att Heroku-databasen kan komma åt den).
För detta använder jag den underbara ngrok .
När jag har installerat behöver jag bara ange följande kommando:
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
Och du behöver bara koppla in db_link
(i huvudsak) till host=ngrock.com port=51727
och du är bra att gå !
4. Gå vidare
Det finns många möjliga förbättringar av detta. Här är några jag redan ser:
- Tänker på skriptet som en standardfunktion för
db_link
funktion - Var mer felsäker om databasstrukturer är olika i säkerhetskopiering och produktion
- Gör jämförelseverktyg mellan databasresultat och säkerhetskopieringsresultat (för att endast returnera olika rader)
- Hantera enkla kopplingar
- Och ännu mer skulle vara att ha en applikationsnivåadapter (t.ex. ActiveRecord in Rails) som skulle kunna tillåta manipulering av backend-objekt istället för rå SQL som nu
Hoppas jag var tydlig! Be om mer information annars