PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Wie kann ich bestimmte Daten aus einer früheren Sicherung auf Postgres Heroku wiederherstellen? (zB versehentlich gelöschte Zeilen)

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 die restore Funktion. Wählen Sie Ihre Dump-Datei aus und klicken Sie auf Restore 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