Shrnutí / TL;DR
Ve 3 krocích budete moci provést velmi jednoduše:
INSERT INTO production_db.table_name
SELECT * FROM backup_db.table_name -- backup_db being remote
Nejprve lokálně nainstalujte zálohu, za druhé získejte SQL skript, za třetí otevřete svůj localhost vnějšímu světu pomocí ngrok .
Jdeme?
1. Stáhněte si soubor výpisu na Heroku a někam to vyhodit:
- Můžete to udělat ve vzdálené databázi, pokud máte k dispozici nějaké servery. Ale pokud jako já nechcete poskytovat další produkční databázi na Heroku nebo někde jinde, lokálně to zcela postačí.
- Rád používám PGAdmin
(k dispozici v systémech Linux, Mac a Windows), ale pomocí příkazového řádku a
psql
udělá to také (přečtením tohoto příspěvek příkladem) - V PGAdmin byste provedli
Create a database
. Poté na něj klikněte pravým tlačítkem a použijterestore
funkce. Vyberte soubor výpisu a klikněte naRestore
a vše je připraveno:vaše zálohovaná data jsou dostupná místně! Dobrá práce!
2. Přístup k němu ze vzdálené databáze
Chtěl jsem udělat následující:
SELECT * FROM backup_db.table_name
-- So I could then do
INSERT INTO production_db.table_name
SELECT * FROM backup_db.table_name
A byl bych připraven. Super snadné, že? Docela zřejmé? To už se muselo dělat stokrát. No, ne!
Existuje nástroj s názvem db_link
v Postgresu 9.1+, ale je to dost omezující, protože platí následující syntaxe:
SELECT fname, lname FROM db_link('host=localhost dbname=backup-28-08', 'SELECT fname, lname FROM users') AS remote (varchar255 fname varchar255 lname)
Každý název sloupce je třeba zopakovat dvakrát včetně jeho typu. Docela těžké, jsme daleko od jednoduchého SELECT * FROM backup_db.table_name
Cílem je tedy použít information_schema
obsah tabulky, který popisuje každou tabulku s názvy sloupců, jejich typy atd. Tuto otázku jsem našel na SO:Určení seznamu definic sloupců dblink z místního existujícího typu
což mi hodně pomohlo (Díky bentrm
).
Ale jeho řešením byl dvoustupňový proces, nejprve vygenerování funkce a pak její dotazování:
SELECT dblink_star_func('dbname=ben', 'public', 'test');
SELECT * FROM star_test() WHERE data = 'success';
A to jsem stále mířil na 1 vložku. Po nějaké malé bolesti (nebýt SQL Guru) zde je podstata:https://gist.github. com/augnustin/d30973ea8b5bf0067841
Nyní mohu udělat:
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)
Skvělé, že?
3. Vzdálený přístup k localhost
Pokud je vaše vzdálená databáze již dostupná z internetu (=má IP adresu, název domény např. pro Heroku, bude to vypadat takto:ec2-54-217-229-169.eu-west-1.compute.amazonaws.com:5672/df68cfpbufjd9p
) tento krok můžete přeskočit . Pokud ale používáte místní databázi, musíte ji zpřístupnit z vnějšího světa (aby k ní měla databáze Heroku přístup).
K tomu používám úžasný ngrok .
Po instalaci stačí zadat následující příkaz:
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
A budete muset připojit pouze db_link
(v podstatě) na host=ngrock.com port=51727
a můžete jít !
4. Jdeme dále
Existuje mnoho možných vylepšení. Zde jsou některé, které už vidím:
- Skript považujeme za výchozí funkci
db_link
funkce - Být odolnější proti chybám, pokud se databázové struktury liší v zálohování a produkci
- Vytváření nástroje pro porovnávání výsledků databáze a výsledků zálohování (navrácení pouze rozdílových řádků)
- Obsluha jednoduchých spojení
- A ještě dále by bylo mít adaptér na úrovni aplikace (např. ActiveRecord v Rails), který by umožňoval manipulaci s objekty backendu namísto surového SQL, jako je tomu nyní
Doufám, že jsem měl jasno! V opačném případě se zeptejte na další podrobnosti