sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Cómo restaurar datos específicos de una copia de seguridad anterior en Postgres Heroku? (Por ejemplo, filas borradas accidentalmente)

Resumen / TL;DR

En 3 pasos podrás ejecutar de forma muy sencilla:

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

Primero instale la copia de seguridad localmente, luego obtenga un script SQL, tercero abra su host local al mundo exterior con ngrok .

¿Vamos?

1. Descargue su archivo de volcado en Heroku y volcarlo en algún lugar:

  • Puede hacerlo en una base de datos remota si tiene algunos servidores disponibles. Pero si, como yo, no desea aprovisionar otra base de datos de producción en Heroku o en otro lugar, lo hará localmente.
  • Me gusta usar PGAdmin (disponible en Linux, Mac y Windows), pero usando la línea de comando y psql también lo hará (al leer esto publicar por ejemplo)
  • En PGAdmin, haría Create a database . Luego haga clic derecho sobre él y use restore función. Seleccione su archivo de volcado, haga clic en Restore y ya está todo listo:¡sus datos de copia de seguridad están disponibles localmente! ¡Buen trabajo!

2. Acceda desde su base de datos remota

Quería hacer lo siguiente:

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

Y estaría todo listo. Súper fácil, ¿verdad? ¿Bastante obvio? Esto debe haberse hecho cientos de veces ya. ¡Pues no!

Hay una utilidad llamada db_link en Postgres 9.1+, pero es bastante restrictivo ya que se aplica la siguiente sintaxis:

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

Cada nombre de columna debe repetirse dos veces, incluido su tipo. Bastante pesado, estamos lejos del simple SELECT * FROM backup_db.table_name

Entonces, la idea aquí es usar el information_schema contenido de la tabla, que describe cada tabla con sus nombres de columna, sus tipos, etc. Encontré esta pregunta en SO:Especifique la lista de definición de columna dblink de un tipo local existente lo que me ayudó mucho (Gracias bentrm ).

Pero su solución fue un proceso de dos pasos, primero generar una función y luego consultarla:

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

Y todavía estaba apuntando a una línea 1. Después de un poco de dolor (no ser un gurú de SQL), aquí está la esencia:https://gist.github. com/augnustin/d30973ea8b5bf0067841

Ahora puedo hacer:

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)

Impresionante, ¿verdad?

3. Acceda a localhost de forma remota

Si su base de datos remota ya está disponible en Internet (=tiene una dirección IP, un nombre de dominio, por ejemplo, para Heroku, se verá así:ec2-54-217-229-169.eu-west-1.compute.amazonaws.com:5672/df68cfpbufjd9p ) puede omitir este paso . Pero si usa su base de datos local, debe hacer que esté disponible desde el mundo exterior (para que la base de datos de Heroku pueda acceder a ella).

Para esto, uso el maravilloso ngrok .

Una vez instalado solo necesito ingresar el siguiente comando:

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    

Y solo necesitaría conectar db_link (en esencia) a host=ngrock.com port=51727 y estás bueno para ir !

4. Yendo más lejos

Hay muchas mejoras posibles para esto. Aquí hay algunos que ya veo:

  • Considerar la secuencia de comandos como una función predeterminada para db_link función
  • Ser más a prueba de errores si las estructuras de la base de datos son diferentes en la copia de seguridad y la producción
  • Hacer una herramienta de comparación entre los resultados de la base de datos y los resultados de la copia de seguridad (solo para devolver líneas de diferenciación)
  • Manejar uniones simples
  • Y aún más sería tener un adaptador de nivel de aplicación (por ejemplo, ActiveRecord en Rails) que podría permitir la manipulación de objetos de back-end en lugar de SQL sin formato como ahora

¡Espero haber sido claro! Solicite más detalles de lo contrario