Podsumowanie / TL;DR
W 3 krokach będziesz w stanie wykonać bardzo prosto:
INSERT INTO production_db.table_name
SELECT * FROM backup_db.table_name -- backup_db being remote
Najpierw zainstaluj kopię zapasową lokalnie, po drugie pobierz skrypt SQL, po trzecie otwórz swój lokalny host na świat zewnętrzny za pomocą ngrok .
Chodźmy?
1. Pobierz plik zrzutu na Heroku i zrzuć to gdzieś:
- Możesz to zrobić w zdalnej bazie danych, jeśli masz dostępne serwery. Ale jeśli tak jak ja nie chcesz udostępniać innej produkcyjnej bazy danych w Heroku lub w innym miejscu, lokalnie całkowicie to zrobi.
- Lubię używać PGAdmin
(dostępne w systemach Linux, Mac i Windows), ale za pomocą wiersza poleceń i
psql
też zrobi (czytając ten post przez przykład) - W PGAdmin zrobisz
Create a database
. Następnie kliknij prawym przyciskiem myszy i użyjrestore
funkcjonować. Wybierz plik zrzutu, kliknijRestore
i gotowe:Twoje dane kopii zapasowej są dostępne lokalnie! Dobra robota!
2. Uzyskaj do niego dostęp ze zdalnej bazy danych
Chciałem wykonać następujące czynności:
SELECT * FROM backup_db.table_name
-- So I could then do
INSERT INTO production_db.table_name
SELECT * FROM backup_db.table_name
I byłbym gotowy. Super łatwe, prawda? Dość oczywiste? Musiało to być zrobione już setki razy. Cóż, nie!
Istnieje narzędzie o nazwie db_link
w Postgresie 9.1+, ale jest to dość ograniczające, ponieważ obowiązuje następująca składnia:
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ą nazwę kolumny należy powtórzyć dwukrotnie, łącznie z jej typem. Dość ciężkie, daleko nam do prostego SELECT * FROM backup_db.table_name
Pomysł polega na tym, aby użyć information_schema
zawartość tabeli, która opisuje każdą tabelę z nazwami kolumn, jej typami itp. Znalazłem to pytanie na SO:Określ listę definicji kolumn dblink z lokalnego istniejącego typu
co mi bardzo pomogło (Dzięki bentrm
).
Ale jego rozwiązanie było procesem dwuetapowym, najpierw generując funkcję, a następnie wysyłając zapytanie:
SELECT dblink_star_func('dbname=ben', 'public', 'test');
SELECT * FROM star_test() WHERE data = 'success';
A ja wciąż celowałem w 1 liniowiec. Po pewnym bólu (nie będąc guru SQL), oto podsumowanie:https://gist.github. com/augnustin/d30973ea8b5bf0067841
Teraz mogę zrobić:
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)
Niesamowite, prawda?
3. Uzyskaj zdalny dostęp do hosta lokalnego
Jeśli twoja zdalna baza danych jest już dostępna w internecie (=ma adres IP, nazwę domeny Np. dla Heroku będzie wyglądać tak:ec2-54-217-229-169.eu-west-1.compute.amazonaws.com:5672/df68cfpbufjd9p
) możesz pominąć ten krok . Ale jeśli korzystasz z lokalnej bazy danych, musisz udostępnić ją ze świata zewnętrznego (aby baza danych Heroku miała do niej dostęp).
W tym celu używam wspaniałego ngrok .
Po zainstalowaniu wystarczy wprowadzić następujące polecenie:
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
I wystarczy tylko podłączyć db_link
(w treści) do host=ngrock.com port=51727
i jesteś gotowy do wyjścia !
4. Idąc dalej
Istnieje wiele możliwych ulepszeń. Oto kilka, które już widzę:
- Uważanie skryptu za domyślną funkcję
db_link
funkcja - Większa odporność na błędy, jeśli struktury bazy danych są różne w przypadku tworzenia kopii zapasowych i produkcji
- Tworzenie narzędzia do porównywania wyników bazy danych z wynikami kopii zapasowej (aby zwracać tylko linie różnicujące)
- Obsługuj proste połączenia
- A jeszcze dalej byłoby mieć adapter na poziomie aplikacji (np. ActiveRecord w Rails), który umożliwiałby manipulowanie obiektami zaplecza zamiast surowego SQL, jak teraz
Mam nadzieję, że zrozumiałem! W przeciwnym razie poproś o więcej szczegółów