Ringkasan / TL;DR
Dalam 3 langkah Anda akan dapat mengeksekusi dengan sangat sederhana:
INSERT INTO production_db.table_name
SELECT * FROM backup_db.table_name -- backup_db being remote
Pertama instal cadangan secara lokal, kedua dapatkan skrip SQL, ketiga buka localhost Anda ke dunia luar dengan ngrok .
Ayo pergi?
1. Unduh file dump Anda di Heroku dan buang di suatu tempat:
- Anda dapat melakukannya pada database jarak jauh jika Anda memiliki beberapa server yang tersedia. Tetapi jika seperti saya, Anda tidak ingin menyediakan basis data produksi lain di Heroku atau di tempat lain, secara lokal akan melakukannya.
- Saya suka menggunakan PGAdmin
(tersedia di Linux, Mac dan Windows), tetapi menggunakan baris perintah dan
psql
juga akan melakukannya (dengan membaca posting dengan contoh) - Di PGAdmin, Anda akan melakukan
Create a database
. Kemudian klik kanan padanya dan gunakanrestore
fungsi. Pilih file dump Anda, klikRestore
dan Anda sudah siap :data cadangan Anda tersedia secara lokal! Kerja bagus!
2. Akses dari basis data jarak jauh Anda
Saya ingin melakukan hal berikut:
SELECT * FROM backup_db.table_name
-- So I could then do
INSERT INTO production_db.table_name
SELECT * FROM backup_db.table_name
Dan saya akan siap. Sangat mudah, bukan? Cukup jelas? Ini pasti sudah dilakukan ratusan kali. Yah, tidak!
Ada utilitas bernama db_link
di Postgres 9.1+, tetapi cukup membatasi karena sintaks berikut berlaku:
SELECT fname, lname FROM db_link('host=localhost dbname=backup-28-08', 'SELECT fname, lname FROM users') AS remote (varchar255 fname varchar255 lname)
Setiap nama kolom perlu diulang dua kali termasuk jenisnya. Cukup berat, kami jauh dari yang sederhana SELECT * FROM backup_db.table_name
Jadi idenya di sini adalah menggunakan information_schema
konten tabel, yang menjelaskan setiap tabel dengan nama kolomnya, jenisnya, dll. Saya menemukan pertanyaan ini di SO:Tentukan daftar definisi kolom dblink dari jenis lokal yang ada
yang membantu saya banyak (Terima kasih bentrm
).
Tetapi solusinya adalah proses dua langkah, pertama menghasilkan fungsi, lalu menanyakannya:
SELECT dblink_star_func('dbname=ben', 'public', 'test');
SELECT * FROM star_test() WHERE data = 'success';
Dan saya masih membidik 1 liner. Setelah sedikit kesulitan (bukan menjadi SQL Guru), inilah intinya :https://Gist.github. com/augnustin/d30973ea8b5bf0067841
Sekarang saya bisa melakukan:
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)
Luar biasa, bukan?
3. Akses localhost dari jarak jauh
Jika basis data jarak jauh Anda sudah tersedia dari internet (=memiliki alamat IP, nama domain Misalnya untuk Heroku akan terlihat seperti:ec2-54-217-229-169.eu-west-1.compute.amazonaws.com:5672/df68cfpbufjd9p
) Anda dapat melewati langkah ini . Tetapi jika Anda menggunakan database lokal, Anda harus membuatnya tersedia dari dunia luar (agar database Heroku dapat mengaksesnya).
Untuk ini, saya menggunakan luar biasa ngrok .
Setelah terinstal, saya hanya perlu memasukkan perintah berikut:
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
Dan Anda hanya perlu mencolokkan db_link
(pada intinya) ke host=ngrock.com port=51727
dan Anda baik untuk pergi !
4. Melangkah lebih jauh
Ada banyak kemungkinan perbaikan untuk ini. Ini beberapa yang sudah saya lihat:
- Mempertimbangkan skrip sebagai fitur default untuk
db_link
fungsi - Menjadi lebih tahan kesalahan jika struktur basis data berbeda dalam pencadangan dan produksi
- Membuat alat perbandingan antara hasil basis data dan hasil pencadangan (untuk hanya mengembalikan garis yang berbeda)
- Menangani penggabungan sederhana
- Dan lebih jauh lagi adalah memiliki adaptor level aplikasi (Misalnya ActiveRecord di Rails) yang dapat memungkinkan manipulasi objek backend alih-alih SQL mentah seperti sekarang
Semoga saya jelas! Silakan tanyakan lebih detail jika tidak