Samenvatting / TL;DR
In 3 stappen kunt u heel eenvoudig uitvoeren:
INSERT INTO production_db.table_name
SELECT * FROM backup_db.table_name -- backup_db being remote
Installeer eerst de back-up lokaal, verkrijg ten tweede een SQL-script, ten derde open je localhost naar de buitenwereld met ngrok .
Laten we gaan?
1. Download uw dumpbestand op Heroku en dump het ergens:
- Je kunt dat doen op een externe database als je servers beschikbaar hebt. Maar als je, net als ik, geen andere productiedatabase op Heroku of ergens anders wilt voorzien, is lokaal voldoende.
- Ik gebruik graag PGAdmin
(beschikbaar op Linux, Mac en Windows), maar met gebruik van de opdrachtregel en
psql
zal ook doen (door deze posten door voorbeeld) - In PGAdmin doet u
Create a database
. Klik er dan met de rechtermuisknop op en gebruik derestore
functie. Selecteer uw dumpbestand, klik opRestore
en je bent helemaal klaar:je back-upgegevens zijn lokaal beschikbaar! Goed gedaan!
2. Open het vanuit uw externe database
Ik wilde het volgende doen:
SELECT * FROM backup_db.table_name
-- So I could then do
INSERT INTO production_db.table_name
SELECT * FROM backup_db.table_name
En ik zou helemaal klaar zijn. Super makkelijk, toch? Vrij duidelijk? Dit moet al honderden keren zijn gedaan. Nou, nee!
Er is een hulpprogramma genaamd db_link
in Postgres 9.1+, maar het is behoorlijk beperkend omdat de volgende syntaxis van toepassing is:
SELECT fname, lname FROM db_link('host=localhost dbname=backup-28-08', 'SELECT fname, lname FROM users') AS remote (varchar255 fname varchar255 lname)
Elke kolomnaam moet twee keer worden herhaald, inclusief het type. Vrij zwaar, we zijn verre van de eenvoudige SELECT * FROM backup_db.table_name
Dus het idee hier is om het information_schema
. te gebruiken tabelinhoud, die elke tabel beschrijft met de kolomnamen, de typen enz. Ik vond deze vraag op SO:Specificeer dblink kolomdefinitielijst van een lokaal bestaand type
wat me veel heeft geholpen (Bedankt bentrm
).
Maar de oplossing was een proces van twee stappen, eerst een functie genereren en deze vervolgens opvragen:
SELECT dblink_star_func('dbname=ben', 'public', 'test');
SELECT * FROM star_test() WHERE data = 'success';
En ik mikte nog steeds op een 1-liner. Na wat pijn (geen SQL-goeroe zijn), is hier de samenvatting:https://gist.github. com/augnustin/d30973ea8b5bf0067841
Ik kan nu het volgende doen:
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)
Geweldig, toch?
3. Toegang krijgen tot localhost op afstand
Als uw externe database al beschikbaar is vanaf internet (=heeft een IP-adres, een domeinnaam, bijvoorbeeld voor Heroku, ziet het er als volgt uit:ec2-54-217-229-169.eu-west-1.compute.amazonaws.com:5672/df68cfpbufjd9p
) je kunt deze stap overslaan . Maar als u uw lokale database gebruikt, moet u deze van de buitenwereld beschikbaar maken (zodat de Heroku-database er toegang toe heeft).
Hiervoor gebruik ik de prachtige ngrok .
Eenmaal geïnstalleerd hoef ik alleen de volgende opdracht in te voeren:
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
En u hoeft alleen db_link
. aan te sluiten (in wezen) naar host=ngrock.com port=51727
en je bent goed om te gaan !
4. Verder gaan
Hierin zijn veel verbeteringen mogelijk. Hier zijn er een paar die ik al zie:
- Het script beschouwen als een standaardfunctie voor
db_link
functie - Foutbestendiger zijn als databasestructuren verschillen in back-up en productie
- Een vergelijkingstool maken tussen databaseresultaten en back-upresultaten (om alleen afwijkende regels terug te geven)
- Eenvoudige joins afhandelen
- En nog verder zou het hebben van een adapter op applicatieniveau (bijv. ActiveRecord in Rails) die manipulatie van backend-objecten mogelijk zou maken in plaats van onbewerkte SQL zoals nu
Hoop dat ik duidelijk was! Vraag anders om meer details