Zusammenfassung / TL;DR
In 3 Schritten können Sie ganz einfach ausführen:
INSERT INTO production_db.table_name
SELECT * FROM backup_db.table_name -- backup_db being remote
Installieren Sie zuerst das Backup lokal, zweitens holen Sie sich ein SQL-Skript, drittens öffnen Sie Ihren Localhost mit ngrok .
Lass uns gehen?
1. Laden Sie Ihre Dump-Datei auf Heroku herunter und es irgendwo ablegen:
- Sie können dies auf einer entfernten Datenbank tun, wenn Sie einige Server zur Verfügung haben. Aber wenn Sie wie ich keine weitere Produktionsdatenbank auf Heroku oder woanders bereitstellen möchten, reicht lokal völlig aus.
- Ich verwende gerne PGAdmin
(verfügbar unter Linux, Mac und Windows), aber mit Befehlszeile und
psql
geht auch (durch Lesen dieses posten Beispiel) - In PGAdmin würden Sie
Create a database
ausführen . Klicken Sie dann mit der rechten Maustaste darauf und verwenden Sie dierestore
Funktion. Wählen Sie Ihre Dump-Datei aus und klicken Sie aufRestore
und schon sind Sie fertig:Ihre Backup-Daten sind lokal verfügbar! Gute Arbeit!
2. Greifen Sie von Ihrer entfernten Datenbank darauf zu
Ich wollte Folgendes tun:
SELECT * FROM backup_db.table_name
-- So I could then do
INSERT INTO production_db.table_name
SELECT * FROM backup_db.table_name
Und ich wäre fertig. Supereinfach, oder? Ganz schön offensichtlich? Das muss schon hunderte Male gemacht worden sein. Nun, nein!
Es gibt ein Dienstprogramm namens db_link
in Postgres 9.1+, aber es ist ziemlich einschränkend, da die folgende Syntax gilt:
SELECT fname, lname FROM db_link('host=localhost dbname=backup-28-08', 'SELECT fname, lname FROM users') AS remote (varchar255 fname varchar255 lname)
Jeder Spaltenname muss einschließlich seines Typs zweimal wiederholt werden. Ziemlich schwer, wir sind weit entfernt von dem einfachen SELECT * FROM backup_db.table_name
Die Idee hier ist also, das information_schema
zu verwenden Tabelleninhalt, der jede Tabelle mit ihren Spaltennamen, ihren Typen usw. beschreibt. Ich habe diese Frage auf SO gefunden:Spaltendefinitionsliste von dblink von einem lokal existierenden Typ angeben
was mir sehr geholfen hat (Dank bentrm
).
Aber seine Lösung war ein zweistufiger Prozess, zuerst eine Funktion generierend, dann abfragend:
SELECT dblink_star_func('dbname=ben', 'public', 'test');
SELECT * FROM star_test() WHERE data = 'success';
Und ich zielte immer noch auf einen 1-Liner ab. Nach einiger Mühe (kein SQL-Guru) ist hier das Wesentliche:https://gist.github. com/augnustin/d30973ea8b5bf0067841
Ich kann jetzt:
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)
Großartig, oder?
3. Fernzugriff auf localhost
Wenn Ihre Remote-Datenbank bereits aus dem Internet verfügbar ist (=eine IP-Adresse, einen Domänennamen hat), sieht dies z. B. für Heroku so aus:ec2-54-217-229-169.eu-west-1.compute.amazonaws.com:5672/df68cfpbufjd9p
) Sie können diesen Schritt überspringen . Aber wenn Sie Ihre lokale Datenbank verwenden, müssen Sie sie von der Außenwelt verfügbar machen (damit die Heroku-Datenbank darauf zugreifen kann).
Dafür verwende ich den wunderbaren ngrok .
Nach der Installation muss ich nur noch folgenden Befehl eingeben:
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
Und Sie müssten nur db_link
anschließen (im Wesentlichen) an host=ngrock.com port=51727
und Sie sind gut zu gehen !
4. Weiter gehen
Hier gibt es viele Verbesserungsmöglichkeiten. Hier sind einige, die ich bereits sehe:
- Das Skript als Standardfunktion für
db_link
betrachten Funktion - Fehlersicherer sein, wenn Datenbankstrukturen in Backup und Produktion unterschiedlich sind
- Vergleichstool zwischen Datenbankergebnissen und Backup-Ergebnissen erstellen (um nur abweichende Zeilen zurückzugeben)
- Einfache Verknüpfungen verarbeiten
- Und noch weiter wäre es, einen Adapter auf Anwendungsebene zu haben (z. B. ActiveRecord in Rails), der die Manipulation von Backend-Objekten anstelle von rohem SQL wie jetzt ermöglichen könnte
Hoffe ich war klar! Bitte fragen Sie andernfalls nach weiteren Details