PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Comment restaurer des données spécifiques à partir d'une sauvegarde précédente sur Postgres Heroku ? (Par exemple, lignes supprimées accidentellement)

Résumé / TL;DR

En 3 étapes vous pourrez exécuter très simplement :

INSERT INTO production_db.table_name
SELECT * FROM backup_db.table_name -- backup_db being remote

Installez d'abord la sauvegarde localement, deuxièmement obtenez un script SQL, troisièmement ouvrez votre hôte local au monde extérieur avec ngrok .

Allons-y ?

1. Téléchargez votre fichier de vidage sur Heroku et déposez-le quelque part :

  • Vous pouvez le faire sur une base de données distante si vous avez des serveurs disponibles. Mais si, comme moi, vous ne souhaitez pas provisionner une autre base de données de production sur Heroku ou ailleurs, cela suffira en local.
  • J'aime utiliser PGAdmin (disponible sur Linux, Mac et Windows), mais en utilisant la ligne de commande et psql fera également (en lisant ceci poster par exemple)
  • Dans PGAdmin, vous feriez Create a database . Ensuite, faites un clic droit dessus et utilisez le restore fonction. Sélectionnez votre fichier de vidage, cliquez sur Restore et le tour est joué :vos données de sauvegarde sont disponibles localement ! Bon travail !

2. Accédez-y depuis votre base de données distante

Je voulais faire ce qui suit :

SELECT * FROM backup_db.table_name
-- So I could then do
INSERT INTO production_db.table_name
SELECT * FROM backup_db.table_name

Et je serais prêt. Super facile, non ? Assez évident? Cela a dû déjà être fait des centaines de fois. Et bien non !

Il existe un utilitaire appelé db_link dans Postgres 9.1+, mais c'est assez contraignant car la syntaxe suivante s'applique :

SELECT fname, lname FROM db_link('host=localhost dbname=backup-28-08', 'SELECT fname, lname FROM users') AS remote (varchar255 fname varchar255 lname)

Chaque nom de colonne doit être répété deux fois, y compris son type. Assez lourd, on est loin du simple SELECT * FROM backup_db.table_name

Donc l'idée ici est d'utiliser le information_schema contenu de la table, qui décrit chaque table avec ses noms de colonnes, ses types, etc. J'ai trouvé cette question sur SO :Spécifier la liste de définition de colonne dblink à partir d'un type existant local qui m'a beaucoup aidé (Merci bentrm ).

Mais sa solution était un processus en deux étapes, générant d'abord une fonction, puis l'interrogeant :

SELECT dblink_star_func('dbname=ben', 'public', 'test');
SELECT * FROM star_test() WHERE data = 'success';

Et je visais toujours un 1 ligne. Après un peu de peine (n'étant pas un gourou du SQL), voici le Gist :https://gist.github. com/augnustin/d30973ea8b5bf0067841

Je peux maintenant faire :

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)

Génial, non ?

3. Accéder à distance à localhost

Si votre base de données distante est déjà disponible sur Internet (=a une adresse IP, un nom de domaine Par exemple, pour Heroku, cela ressemblera à :ec2-54-217-229-169.eu-west-1.compute.amazonaws.com:5672/df68cfpbufjd9p ) vous pouvez ignorer cette étape . Mais si vous utilisez votre base de données locale, vous devez la rendre disponible depuis le monde extérieur (afin que la base de données Heroku puisse y accéder).

Pour cela, j'utilise le merveilleux ngrok .

Une fois installé, il me suffit d'entrer la commande suivante :

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    

Et vous n'auriez qu'à brancher db_link (dans l'essentiel) à host=ngrock.com port=51727 et vous êtes prêt à partir !

4. Aller plus loin

Il y a beaucoup d'améliorations possibles à cela. En voici quelques-unes que je vois déjà :

  • Considérer le script comme une fonctionnalité par défaut de db_link fonction
  • Être plus à l'épreuve des erreurs si les structures de base de données sont différentes en sauvegarde et en production
  • Création d'un outil de comparaison entre les résultats de la base de données et les résultats de la sauvegarde (pour ne renvoyer que des lignes différentes)
  • Gérer les jointures simples
  • Et encore plus serait d'avoir un adaptateur au niveau de l'application (par exemple, ActiveRecord dans Rails) qui pourrait permettre la manipulation d'objets backend au lieu de SQL brut comme maintenant

J'espère avoir été clair ! Veuillez demander plus de détails sinon