Membuat salinan database di PostgreSQL

730

Apa cara yang benar untuk menyalin seluruh basis data (struktur dan datanya) ke yang baru di pgAdmin?

egaga
sumber

Jawaban:

1121

Postgres memungkinkan penggunaan basis data apa pun yang ada di server sebagai templat saat membuat basis data baru. Saya tidak yakin apakah pgAdmin memberi Anda opsi pada dialog buat database tetapi Anda harus dapat menjalankan yang berikut di jendela kueri jika tidak:

CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;

Namun, Anda mungkin mendapatkan:

ERROR:  source database "originaldb" is being accessed by other users

Untuk memutuskan sambungan semua pengguna lain dari basis data, Anda dapat menggunakan kueri ini:

SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity 
WHERE pg_stat_activity.datname = 'originaldb' AND pid <> pg_backend_pid();
lonceng
sumber
68
Perhatikan bahwa originaldb harus dalam keadaan idle (tidak ada transaksi tulis) agar ini berfungsi.
synecdoche
62
di pgAdmin3, di panel Object browser (kiri), saya dapat memilih Servers-> (server saya) -> Databases, klik kanan Databases, dan pilih "Database Baru". Salah satu opsi adalah templat, dan SQL yang digunakan untuk membuat database adalah setara. Hal ini sangat jauh lebih cepat daripada dump / restore pada server yang sama.
jwhitlock
22
Saya tahu ini Q / A yang lama, tapi saya merasa perlu klarifikasi: Ketika @synecdoche mengatakan bahwa originaldb pasti idle, itu berarti tidak ada kemungkinan menulis sama sekali. "Menyalin" database dengan cara ini tidak mengunci originaldb. PostgreSQL hanya mencegah memulai penyalinan jika ada orang lain yang mengakses originaldb - tidak setelah penyalinan dimulai, jadi ada kemungkinan bahwa koneksi lain dapat memodifikasi basis data ketika "penyalinan" sedang terjadi. IMHO, ini mungkin jawaban termudah, tetapi "yang terbaik" adalah dengan menggunakan dump / restore.
Josh
10
Saya baru saja melihat ini. @Josh: ketika originaldb sedang disalin dengan membuat database dengan templat, postgresql tidak mengizinkan membuat koneksi baru ke sana, jadi tidak ada perubahan yang mungkin.
ceteras
4
Perhatikan bahwa jika Anda menggunakan pgAdmin dan menjalankan CREATE DATABASE ... TEMPLATE xxx dari jendela perintah SQL, Anda harus memutuskan koneksi dari database di jendela pgAdmin utama atau Anda akan mendapatkan kesalahan tentang pengguna yang terhubung ke database.
Jack RG
296

Versi baris perintah dari jawaban Bell :

createdb -O ownername -T originaldb newdb

Ini harus dijalankan di bawah hak master database, biasanya postgres.

zbyszek
sumber
5
Ini adalah perintah yang bagus TETAPI Anda akan dapatkan createdb: database creation failed: ERROR: source database "conf" is being accessed by other usersjika Anda mencoba melakukannya pada basis data produksi dan seperti yang diharapkan Anda tidak ingin mematikannya untuk membuat salinan.
sorin
7
Ya, peringatan yang sama berlaku untuk perintah ini, untuk permintaan CREATE DATABASE secara eksplisit. Seperti komentar untuk jawaban Bell di atas katakan, database seharusnya tidak digunakan.
zbyszek
108

Untuk mengkloning database yang ada dengan postgres, Anda dapat melakukannya

/* KILL ALL EXISTING CONNECTION FROM ORIGINAL DB (sourcedb)*/
SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity 
WHERE pg_stat_activity.datname = 'SOURCE_DB' AND pid <> pg_backend_pid();

/* CLONE DATABASE TO NEW ONE(TARGET_DB) */
CREATE DATABASE TARGET_DB WITH TEMPLATE SOURCE_DB OWNER USER_DB;

ITU akan mematikan semua koneksi ke sumber db menghindari kesalahan

ERROR:  source database "SOURCE_DB" is being accessed by other users
Brugolo
sumber
7
+1 untuk menyebutkan solusi skrip untuk menghindari kesalahan akses
bully
14
Pada Postgres 9.2 saya harus mengganti procpiddengan pidagar ini berfungsi
marxjohnson
75

Dalam lingkungan produksi, di mana basis data asli berada di bawah lalu lintas, saya hanya menggunakan:

pg_dump production-db | psql test-db
Tregoreg
sumber
8
Satu masalah yang saya temukan dengan metode ini adalah pg_dump akan membuka transaksinya hingga pemulihan ke dalam database baru selesai, bahkan jika pg_dump benar-benar telah menyelesaikan dumpnya. Ini dapat menyebabkan masalah penguncian dalam beberapa kasus (misalnya, jika pernyataan DDL dijalankan pada DB sumber).
Chris Butler
3
Plus satu untuk tidak menggunakan file perantara sementara.
Ardee Aram
Itu juga solusi saya. Kemarin berhasil, sekarang kendala unik acak dilanggar. Catatan: Saya menjatuhkan semua tabel ke penerima db.
gunzapper
1
@AlexanderMills pg_dump -s? postgresql.org/docs/current/static/app-pgdump.html
Tregoreg
1
Ini mengasumsikan bahwa test-db ada. Jika tidak, buat db baru dengan$ createdb newdb
SamGoody
50

Tidak tahu tentang pgAdmin, tetapi pgdumpmemberi Anda dump database di SQL. Anda hanya perlu membuat database dengan nama yang sama dan lakukan

psql mydatabase < my dump

untuk mengembalikan semua tabel dan datanya serta semua hak akses.

TrayMan
sumber
Terima kasih, saya perlu membuat dump dari server lain, dan sepertinya ini membantu: postgresql.org/docs/8.3/interactive/…
egaga
19
Anda bahkan dapat melakukannya pg_dump -U postgres sourcedb | psql -U postgres newdbwalaupun efisiensi teknik ini mungkin dipertanyakan (karena Anda mungkin pada akhirnya mengubah konteks antara membaca dan menulis)
Frank Farmer
1
Anda bahkan bisa mendapatkan dump Anda dari mesin jarak jauh melalui ssh: ssh dbserver pg_dump DBNAME | psql NEWDB... atau pg_dump DBNAME | ssh otherserver pgsql NEWDB ... Izin dan otentikasi tentu saja perlu ditangani namun Anda ingin menanganinya.
ghoti
23

Pertama, sudosebagai pengguna basis data:

sudo su postgres

Pergi ke baris perintah PostgreSQL:

psql

Buat database baru, berikan hak dan keluar:

CREATE DATABASE new_database_name;
GRANT ALL PRIVILEGES ON DATABASE new_database_name TO my_user;
\d

Salin struktur dan data dari database lama ke yang baru:

pg_dump old_database_name | psql new_database_name
Mathieu Rodic
sumber
bagaimana memastikan bahwa semuanya baik-baik saja bahkan beberapa kesalahan (masalah jaringan) terjadi? Bagaimana cara memeriksa apakah kedua database itu sama setelah migrasi?
BAE
Kesalahan harus ditampilkan di terminal setiap kali ditemukan. Kedua database harus sama setelah operasi. Namun, saya tidak tahu bagaimana memeriksanya ...
Mathieu Rodic
2
Bekerja seperti pesona, saya melakukannya ketika database sedang dalam produksi.
BioRod
Ini tampaknya bekerja dengan baik; Namun, kedua database memiliki ukuran disk yang berbeda \l+. Mengapa perbedaan ukuran?
kosgeinsky
@kosgeinsky ini telah dijawab secara luas di sini: dba.stackexchange.com/a/102089/39386
Mathieu Rodic
18

Saya kumpulkan pendekatan ini bersama dengan contoh-contoh dari atas. Saya sedang mengerjakan server "di bawah beban" dan mendapatkan kesalahan ketika saya mencoba pendekatan dari @zbyszek. Saya juga mencari solusi "command line only".

createdb: database creation failed: ERROR: source database "exampledb" is being accessed by other users.

Inilah yang bekerja untuk saya ( Perintah yang diawali dengan nohupuntuk memindahkan output ke file dan melindungi dari putuskan server ):

  1. nohup pg_dump exampledb > example-01.sql
  2. createdb -O postgres exampledbclone_01

    pengguna saya adalah "postgres"

  3. nohup psql exampledbclone_01 < example-01.sql

fusi27
sumber
15

Di pgAdmin Anda dapat membuat cadangan dari database asli Anda, dan kemudian hanya membuat database baru dan mengembalikan dari cadangan yang baru saja dibuat:

  1. Klik kanan basis data sumber, Cadangan ... dan buang ke file.
  2. Klik kanan, Objek Baru, Database Baru ... dan beri nama tujuan.
  3. Klik kanan database baru, Pulihkan ... dan pilih file Anda.
Isomorph
sumber
Saya memiliki tabel terkait melalui kunci asing dan ini berfungsi dengan baik.
Randall Blake
12

Apa cara yang benar untuk menyalin seluruh basis data (struktur dan datanya) ke yang baru di pgAdmin?

Menjawab:

CREATE DATABASE newdb WITH TEMPLATE originaldb;

Sudah dicoba dan diuji.

Anirban Chakrabarti
sumber
3
Ini membutuhkan originaldb untuk tidak digunakan. Metode Isomorph tidak.
Bradley
2
Jawaban yang sama diberikan hampir tiga tahun sebelum jawaban Anda
Jason S
8

Dari dokumentasi , tidak disarankan menggunakan createdbatau CREATE DATABASEdengan templat:

Meskipun dimungkinkan untuk menyalin database selain template1 dengan menetapkan namanya sebagai templat, ini belum (belum) dimaksudkan sebagai fasilitas "COPY DATABASE" untuk tujuan umum. Keterbatasan utama adalah bahwa tidak ada sesi lain yang dapat dihubungkan ke database templat saat sedang disalin. BUAT DATABASE akan gagal jika koneksi lain ada ketika mulai; jika tidak, koneksi baru ke basis data templat akan dikunci hingga BUAT DATABASE selesai.

pg_dumpatau pg_dumpallmerupakan cara yang baik untuk menyalin database DAN SEMUA DATA. Jika Anda menggunakan GUI seperti pgAdmin, perintah ini dipanggil di belakang layar saat Anda menjalankan perintah cadangan. Menyalin ke database baru dilakukan dalam dua fase: Pencadangan dan Pemulihan

pg_dumpallmenyimpan semua database di cluster PostgreSQL. Kerugian dari pendekatan ini adalah bahwa Anda berakhir dengan file teks berpotensi sangat besar yang penuh dengan SQL yang diperlukan untuk membuat database dan mengisi data. Keuntungan dari pendekatan ini adalah Anda mendapatkan semua peran (izin) untuk cluster secara gratis. Untuk membuang semua database, lakukan ini dari akun pengguna super

pg_dumpall > db.out

dan mengembalikan

psql -f db.out postgres

pg_dumpmemiliki beberapa opsi kompresi yang memberi Anda file yang jauh lebih kecil. Saya memiliki basis data produksi yang saya backup dua kali sehari dengan menggunakan cron job

pg_dump --create --format=custom --compress=5 --file=db.dump mydatabase

di mana compresslevel kompresi (0 hingga 9) dan creatememberitahu pg_dumpuntuk menambahkan perintah untuk membuat database. Pulihkan (atau pindah ke cluster baru) dengan menggunakan

pg_restore -d newdb db.dump

di mana newdb adalah nama database yang ingin Anda gunakan.

Hal-hal lain untuk dipikirkan

PostgreSQL menggunakan ROLES untuk mengelola izin. Ini tidak disalin oleh pg_dump. Kami juga belum menangani pengaturan di postgresql.conf dan pg_hba.conf (jika Anda memindahkan database ke server lain). Anda harus mencari tahu pengaturan conf sendiri. Tetapi ada trik yang baru saya temukan untuk mendukung peran. Peran dikelola di tingkat gugus dan Anda dapat meminta pg_dumpallcadangan hanya peran dengan --roles-onlysakelar baris perintah.

bfris
sumber
7

PostgreSQL 9.1.2:

$ CREATEDB new_db_name -T orig_db_name -O db_user;
Arta
sumber
3
Ini mungkin diterapkan karena CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;dan sebagai akibatnya mengharuskan database asli harus idle (tidak ada koneksi dengan akses tulis) dan koneksi baru ke database asli dicegah saat penyalinan sedang dalam proses. Jika Anda senang dengan itu, ini berhasil.
Mikko Rantalainen
Detail yang bagus. Terima kasih!
Arta
6

Bagi mereka yang masih tertarik, saya telah membuat skrip bash yang melakukan (kurang lebih) apa yang diinginkan penulis. Saya harus membuat salinan database bisnis harian pada sistem produksi, skrip ini tampaknya melakukan trik. Ingatlah untuk mengubah nama database / nilai pengguna / pw.

#!/bin/bash

if [ 1 -ne $# ]
then
  echo "Usage `basename $0` {tar.gz database file}"
  exit 65;
fi

if [ -f "$1" ]
then
  EXTRACTED=`tar -xzvf $1`
  echo "using database archive: $EXTRACTED";
else
  echo "file $1 does not exist"
  exit 1
fi


PGUSER=dbuser
PGPASSWORD=dbpw
export PGUSER PGPASSWORD

datestr=`date +%Y%m%d`


dbname="dbcpy_$datestr"
createdbcmd="CREATE DATABASE $dbname WITH OWNER = postgres ENCODING = 'UTF8' TABLESPACE = pg_default LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8' CONNECTION LIMIT = -1;"
dropdbcmp="DROP DATABASE $dbname"

echo "creating database $dbname"
psql -c "$createdbcmd"

rc=$?
if [[ $rc != 0 ]] ; then
  rm -rf "$EXTRACTED"
  echo "error occured while creating database $dbname ($rc)"
  exit $rc
fi


echo "loading data into database"
psql $dbname < $EXTRACTED > /dev/null

rc=$?

rm -rf "$EXTRACTED"

if [[ $rc != 0 ]] ; then
  psql -c "$dropdbcmd"
  echo "error occured while loading data to database $dbname ($rc)"
  exit $rc
fi


echo "finished OK"
Dariusz
sumber
5

Untuk membuat dump basis data

cd /var/lib/pgsql/
pg_dump database_name> database_name.out

Untuk memulihkan dump database

psql -d template1
CREATE DATABASE database_name WITH  ENCODING 'UTF8' LC_CTYPE 'en_US.UTF-8' LC_COLLATE 'en_US.UTF-8' TEMPLATE template0;
CREATE USER  role_name WITH PASSWORD 'password';
ALTER DATABASE database_name OWNER TO role_name;
ALTER USER role_name CREATEDB;
GRANT ALL PRIVILEGES ON DATABASE database_name to role_name;


CTR+D(logout from pgsql console)
cd /var/lib/pgsql/

psql -d database_name -f database_name.out
Jagdish Narayandasani
sumber
5

Inilah seluruh proses pembuatan salinan melalui database hanya menggunakan pgadmin4 GUI (via backup dan restore)

Postgres hadir dengan Pgadmin4. Jika Anda menggunakan macOS Anda dapat menekan CMD+ SPACEdan mengetik pgadmin4untuk menjalankannya. Ini akan membuka tab browser di chrome.


Langkah-langkah untuk menyalin

1. Buat cadangan

Lakukan ini dengan mengklik kanan basis data -> "cadangan"

masukkan deskripsi gambar di sini

2. Beri nama file.

Seperti test12345. Klik cadangan. Ini menciptakan dump file biner, tidak dalam .sqlformat

masukkan deskripsi gambar di sini

3. Lihat di mana itu diunduh

Seharusnya ada sembulan di kanan bawah layar Anda. Klik halaman "selengkapnya" untuk melihat ke mana cadangan unduhan Anda

masukkan deskripsi gambar di sini

4. Temukan lokasi file yang diunduh

Dalam hal ini, itu /users/vincenttang

masukkan deskripsi gambar di sini

5. Kembalikan cadangan dari pgadmin

Dengan asumsi Anda melakukan langkah 1 hingga 4 dengan benar, Anda akan memiliki file biner yang dipulihkan. Mungkin suatu saat rekan kerja Anda ingin menggunakan file pemulihan di mesin lokal mereka. Telah mengatakan orang pergi ke pgadmin dan memulihkan

Lakukan ini dengan mengklik kanan basis data -> "restore"

masukkan deskripsi gambar di sini

6. Pilih pencari file

Pastikan untuk memilih lokasi file secara manual, JANGAN seret dan jatuhkan file ke bidang pengunggah di pgadmin. Karena Anda akan mengalami izin kesalahan. Alih-alih, cari file yang baru saja Anda buat:

masukkan deskripsi gambar di sini

7. Temukan file tersebut

Anda mungkin harus mengubah filter di kanan bawah ke "Semua file". Temukan file setelahnya, dari langkah 4. Sekarang tekan tombol "Pilih" kanan untuk mengonfirmasi

masukkan deskripsi gambar di sini

8. Kembalikan file tersebut

Anda akan melihat halaman ini lagi, dengan lokasi file dipilih. Silakan dan kembalikan

masukkan deskripsi gambar di sini

9. Sukses

Jika semuanya baik, kanan bawah akan memunculkan indikator yang menunjukkan pengembalian yang berhasil. Anda dapat menavigasi ke tabel Anda untuk melihat apakah data telah dipulihkan layak pada setiap tabel.

10. Jika tidak berhasil:

Jika langkah 9 gagal, coba hapus skema publik lama Anda di database Anda. Pergi ke "Alat Kueri"

masukkan deskripsi gambar di sini

Jalankan blok kode ini:

DROP SCHEMA public CASCADE; CREATE SCHEMA public;

masukkan deskripsi gambar di sini

Sekarang coba langkah 5 hingga 9 lagi, itu akan berhasil

EDIT - Beberapa catatan tambahan. Perbarui PGADMIN4 jika Anda mendapatkan kesalahan saat mengunggah dengan sesuatu di sepanjang baris "header pengarsipan 1,14 versi yang tidak didukung" selama pemulihan

Vincent Tang
sumber
3

Jika database memiliki koneksi terbuka, skrip ini dapat membantu. Saya menggunakan ini untuk membuat database uji dari cadangan database produksi langsung setiap malam. Ini mengasumsikan bahwa Anda memiliki file cadangan .SQL dari db produksi (saya melakukan ini dalam webmin).

#!/bin/sh

dbname="desired_db_name_of_test_enviroment"
username="user_name"
fname="/path to /ExistingBackupFileOfLive.sql"

dropdbcmp="DROP DATABASE $dbname"
createdbcmd="CREATE DATABASE $dbname WITH OWNER = $username "

export PGPASSWORD=MyPassword



echo "**********"
echo "** Dropping $dbname"
psql -d postgres -h localhost -U "$username" -c "$dropdbcmp"

echo "**********"
echo "** Creating database $dbname"
psql -d postgres -h localhost -U "$username" -c "$createdbcmd"

echo "**********"
echo "** Loading data into database"
psql -d postgres -h localhost -U "$username" -d "$dbname" -a -f "$fname"
derit
sumber
1

Menggunakan pgAdmin, lepaskan basis data yang ingin Anda gunakan sebagai templat. Kemudian Anda memilihnya sebagai templat untuk membuat database baru, ini menghindari kesalahan yang sudah digunakan.

evergreener2
sumber
0

Jika Anda ingin menyalin seluruh skema, Anda dapat membuat pg_dump dengan perintah berikut:

pg_dump -h database.host.com -d database_name -n schema_name -U database_user --password

Dan ketika Anda ingin mengimpor dump itu, Anda dapat menggunakan:

psql "host=database.host.com user=database_user password=database_password dbname=database_name options=--search_path=schema_name" -f sql_dump_to_import.sql

Info lebih lanjut tentang string koneksi: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING

Atau hanya menggabungkannya dalam satu liner:

pg_dump -h database.host.com -d postgres -n schema_name -U database_user --password | psql "host=database.host.com user=database_user password=database_password dbname=database_name options=--search_path=schema_name”
Maksim Luzik
sumber
0
  1. Buka Jendela Utama di pgAdmin dan kemudian buka Jendela Alat Kueri lainnya
  2. Di jendela utama di pgAdmin,

Putuskan koneksi basis data "templated" yang ingin Anda gunakan sebagai templat.

  1. Goto Jendela Alat Kueri

Jalankan 2 kueri seperti di bawah ini

SELECT pg_terminate_backend(pg_stat_activity.pid) 
    FROM pg_stat_activity 
    WHERE pg_stat_activity.datname = 'TemplateDB' AND pid <> pg_backend_pid(); 

(Pernyataan SQL di atas akan menghentikan semua sesi aktif dengan TemplateDB dan kemudian Anda sekarang dapat memilihnya sebagai templat untuk membuat database TargetDB baru, ini menghindari kesalahan yang sudah digunakan.)

CREATE DATABASE 'TargetDB'
  WITH TEMPLATE='TemplateDB'
       CONNECTION LIMIT=-1;
titushui
sumber
-4

Coba ini:

CREATE DATABASE newdb WITH ENCODING='UTF8' OWNER=owner TEMPLATE=templatedb LC_COLLATE='en_US.UTF-8' LC_CTYPE='en_US.UTF-8' CONNECTION LIMIT=-1;

gl XD

pengguna3108031
sumber