PostgreSQL'de veritabanının bir kopyasını oluşturma


728

Tüm veritabanını (yapısı ve verileri) pgAdmin'de yenisine kopyalamanın doğru yolu nedir?

Yanıtlar:


1120

Postgres, yeni bir veritabanı oluştururken sunucudaki mevcut herhangi bir veritabanının şablon olarak kullanılmasına izin verir. PgAdmin'in veritabanı oluştur iletişim kutusunda size seçenek verip vermediğinden emin değilim, ancak aşağıdaki durumlarda bir sorgu penceresinde aşağıdakileri çalıştırabilmeniz gerekir:

CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;

Yine de şunları alabilirsiniz:

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

Diğer tüm kullanıcıların veritabanıyla olan bağlantısını kesmek için şu sorguyu kullanabilirsiniz:

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

68
Bunun çalışması için originaldb'nin boşta (yazma işlemi yok) olması gerektiğini unutmayın.
synecdoche

62
pgAdmin3'te, Nesne tarayıcısı (solda) bölmesinde Servers-> (sunucum) -> Databasesseçebilir, Veritabanları'na sağ tıklayıp "Yeni Veritabanı" nı seçebilirim. Seçeneklerden biri şablondur ve veritabanını oluşturmak için kullanılan SQL eşdeğerdir. Öyle böylece aynı sunucuyu üzerinde geri / çok daha hızlı bir dökümü daha.
jwhitlock

22
Bunun eski bir Soru-Cevap olduğunu biliyorum, ancak açıklığa ihtiyacı olduğunu hissediyorum: @synecdoche, originaldb'nin boşta olması gerektiğini söylediğinde, bu hiçbir yazma olasılığı olmadığı anlamına gelir. Bir veritabanını bu şekilde "kopyalamak" originaldb'yi kilitlemez. PostgreSQL kopyanın başlatılmasını yalnızca originaldb'ye erişen başkaları varsa önler - kopya başladıktan sonra değil, bu nedenle "kopya" meydana gelirken başka bir bağlantının veritabanını değiştirmesi mümkündür. IMHO, bu en kolay cevap olabilir, ancak "en iyi" döküm / geri yükleme kullanmak olacaktır.
Josh

10
Sadece bunu gördüm. @Josh: originaldb şablon ile veritabanı oluştur tarafından kopyalanırken, postgresql ona yeni bir bağlantı oluşturulmasına izin vermez, bu nedenle değişiklik yapılamaz.
ceteras

4
PgAdmin kullanıyorsanız ve SQL komut penceresinden CREATE DATABASE ... TEMPLATE xxx yürütüyorsanız, ana pgAdmin penceresindeki veritabanından bağlantıyı kesmeniz gerektiğini veya veritabanına bağlı kullanıcılar hakkında hata alacağınızı unutmayın.
Jack RG

296

Bell'in cevabının komut satırı versiyonu :

createdb -O ownername -T originaldb newdb

Bu veritabanı yöneticisi, genellikle postgres ayrıcalıkları altında çalıştırılmalıdır.


5
Bu güzel bir komut ama createdb: database creation failed: ERROR: source database "conf" is being accessed by other usersbir üretim veritabanında yapmaya çalışırsanız alacaksınız ve beklendiği gibi bir kopya oluşturmak için kapatmak istemiyorum.
sorin

7
Evet, bu komut için, CREATE DATABASE çağırma işlemiyle aynı uyarılar uygulanır. Bell'in yukarıdaki cevabının yorumları gibi, veritabanı boşta olmalıdır.
zbyszek

108

Varolan bir veritabanını postgres ile klonlamak için bunu yapabilirsiniz

/* 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;

BT kaynak db hatadan kaçınarak tüm bağlantıyı öldürür

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

7
Erişim hatasını önlemek için bir betik çözümünden bahsettiği için +1
bully

14
Postgres 9.2 Ben bunun için çalışmak için procpidile değiştirmek pidzorunda
marxjohnson

75

Orijinal veritabanının trafik altında olduğu üretim ortamında basitçe kullanıyorum:

pg_dump production-db | psql test-db

8
Bu yöntemle bulduğum bir sorun, pg_dump gerçekte dökümü tamamlamış olsa bile pg_dump'ın yeni veritabanına geri yükleme işlemi tamamlanana kadar işlemini açık tutacağıdır. Bu, bazı durumlarda kilitleme sorunlarına neden olabilir (örneğin, kaynak DB'de bir DDL ifadesi çalıştırılırsa).
Chris Butler

3
Ayrıca geçici ara dosyalar kullanmadığınız için bir tane.
Ardee Aram

Aynı zamanda benim çözümümdü. Dün işe yaradı, şimdi rastgele benzersiz kısıtlama ihlal edildi. Not: Tüm tabloyu alıcı db'ye bırakıyorum.
gunzapper


1
Bu, test-db'nin var olduğunu varsayar. Aksi takdirde, yeni $ createdb newdb
db'yi

50

PgAdmin hakkında bilmiyorum, ancak pgdumpSQL'de veritabanının bir dökümünü veriyor. Yalnızca aynı ada sahip bir veritabanı oluşturmanız ve

psql mydatabase < my dump

tüm tabloları ve verilerini ve tüm erişim ayrıcalıklarını geri yüklemek için.


Teşekkürler, başka bir sunucudan bir dökümü oluşturmam gerekiyordu ve bu yardımcı oluyor gibi görünüyor: postgresql.org/docs/8.3/interactive/…
egaga

19
pg_dump -U postgres sourcedb | psql -U postgres newdbBu tekniğin etkinliği şüpheli olsa bile yapabilirsiniz (muhtemelen okuma ve yazma arasında bağlam geçişi yaptığınızdan)
Frank Farmer

1
Çöplüğünüzü uzak bir makineden ssh: ssh dbserver pg_dump DBNAME | psql NEWDB... veya pg_dump DBNAME | ssh otherserver pgsql NEWDB ... ile alabilirsiniz. Tabii ki izinler ve kimlik doğrulaması elbette bunlarla başa çıkmak istediğinizde ele alınmalıdır.
ghoti

23

İlk sudoolarak, veritabanı kullanıcısı olarak:

sudo su postgres

PostgreSQL komut satırına gidin:

psql

Yeni veritabanını oluşturun, hakları verin ve çıkın:

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

Yapıyı ve verileri eski veritabanından yenisine kopyalayın:

pg_dump old_database_name | psql new_database_name

bazı hatalar (ağ sorunu) bile olsa herşeyin yolunda olduğundan nasıl emin olunur? Geçişten sonra iki veritabanının aynı olup olmadığını nasıl kontrol edebilirim?
BAE

Hatalar karşılaşıldığında terminalde gösterilmelidir. Ameliyattan sonra iki veritabanı aynı olmalıdır. Ancak, bunu nasıl kontrol edeceğimi bilmiyorum ...
Mathieu Rodic

2
Bir cazibe gibi çalışır, veritabanı üretilirken yaptım.
BioRod

Bu iyi çalışıyor gibi görünüyor; ancak, iki veritabanı üzerinden farklı disk boyutlarına sahiptir \l+. Neden boyut farkı?
kosgeinsky

@kosgeinsky Bu konuya kapsamlı bir şekilde cevap verilmiştir: dba.stackexchange.com/a/102089/39386
Mathieu Rodic

18

Bu yaklaşımı yukarıdaki örneklerle bir araya getirdim. Bir "yük altında" sunucu üzerinde çalışıyorum ve @zbyszek yaklaşım denediğinde hata var. Ayrıca bir "sadece komut satırı" çözümü peşindeydim.

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

Benim için işe yarayan şey ( Çıktıyı bir dosyaya taşımak ve sunucu bağlantısının kesilmesini önlemek için eklenmiş komutlarnohup ):

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

    benim kullanıcı "postgres"

  3. nohup psql exampledbclone_01 < example-01.sql


15

PgAdmin'de orijinal veritabanınızdan yedekleme yapabilir ve yeni bir veritabanı oluşturabilir ve yeni oluşturulan yedeklemeden geri yükleyebilirsiniz:

  1. Kaynak veritabanına sağ tıklayın, Yedekle ... ve bir dosyaya dökün.
  2. Sağ tıklayın, Yeni Nesne, Yeni Veritabanı ... ve hedefi adlandırın.
  3. Yeni veritabanına sağ tıklayın, Geri Yükle ... ve dosyanızı seçin.

Yabancı anahtarlar ile ilgili tablolar var ve bu iyi çalıştı.
Randall Blake

12

Tüm veritabanını (yapısı ve verileri) pgAdmin'de yenisine kopyalamanın doğru yolu nedir?

Cevap:

CREATE DATABASE newdb WITH TEMPLATE originaldb;

Denendi ve test edildi.


3
Bu, originaldb'nin kullanılmamasını gerektirir. İzomorf yöntemi böyle değildir.
Bradley

2
Aynı cevap sizden yaklaşık üç yıl önce verildi
Jason S

8

Gönderen belgeler kullanılarak createdbveya CREATE DATABASEşablonlarla teşvik edilmez:

Şablon olarak adını belirterek template1 dışında bir veritabanını kopyalamak mümkün olsa da, bu (henüz) genel amaçlı bir “KOPYA VERİTABANI” tesisi olarak tasarlanmamıştır. Temel sınırlama, kopyalanırken şablon veritabanına başka hiçbir oturumun bağlanamamasıdır. CREATE DATABASE, başlatıldığında başka bir bağlantı varsa başarısız olur; Aksi takdirde, şablon veritabanına yeni bağlantılar CREATE DATABASE tamamlanıncaya kadar kilitlenir.

pg_dumpveya pg_dumpallveritabanı VE TÜM VERİ kopyalama için gitmek için iyi bir yoldur. PgAdmin gibi bir GUI kullanıyorsanız, bir yedekleme komutu yürüttüğünüzde bu komutlar sahne arkasında çağrılır. Yeni bir veritabanına kopyalama iki aşamada gerçekleştirilir: Yedekleme ve Geri Yükleme

pg_dumpalltüm veritabanlarını PostgreSQL kümesine kaydeder. Bu yaklaşımın dezavantajı, veritabanını oluşturmak ve verileri doldurmak için gereken SQL ile dolu çok büyük olasılıkla çok büyük bir metin dosyası elde etmenizdir. Bu yaklaşımın avantajı, kümenin tüm rollerini (izinlerini) ücretsiz olarak almanızdır. Tüm veritabanlarını boşaltmak için bunu süper kullanıcı hesabından yapın

pg_dumpall > db.out

ve geri yüklemek için

psql -f db.out postgres

pg_dumpsize daha küçük dosyalar veren bazı sıkıştırma seçeneklerine sahiptir. Kullanarak bir cron işi ile günde iki kez yedekleme bir üretim veritabanı var

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

compresssıkıştırma seviyesi (0 ila 9) nerede ve veritabanını oluşturmak için komut eklemeyi createsöyler pg_dump. Kullanarak geri yükleyin (veya yeni kümeye taşıyın)

pg_restore -d newdb db.dump

burada newdb, kullanmak istediğiniz veritabanının adıdır.

Düşünülmesi gereken diğer şeyler

PostgreSQL, izinleri yönetmek için ROLES kullanır. Bunlar tarafından kopyalanmaz pg_dump. Ayrıca, (veritabanını başka bir sunucuya taşıyorsanız ) postgresql.conf ve pg_hba.conf'daki ayarlarla da ilgilenmedik . Conf ayarlarını kendi başınıza bulmanız gerekir. Ama rolleri desteklediğim için keşfettiğim bir numara var. Roller küme düzeyinde yönetilir pg_dumpallve --roles-onlykomut satırı anahtarıyla yalnızca rolleri yedeklemeyi isteyebilirsiniz .


7

PostgreSQL 9.1.2:

$ CREATEDB new_db_name -T orig_db_name -O db_user;

3
Bu, muhtemelen CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;orijinal veritabanının boşta kalmasını (yazma erişimine sahip bağlantıların olmaması) gerektirdiği ve kopyalama işlemi devam ederken orijinal veritabanına yeni bağlantıların önlenmesini gerektirdiği için uygulanır. Bundan memnunsanız, bu işe yarar.
Mikko Rantalainen

Güzel detay. Teşekkür ederim!
Arta

6

Hala ilgilenenler için, yazarın ne istediğini (az ya da çok) yapan bir bash betiği buldum. Bir üretim sistemi üzerinde bir günlük iş veritabanı kopyası yapmak zorunda kaldım, bu komut dosyası hile yapmak gibi görünüyor. Veritabanı adını / kullanıcı / pw değerlerini değiştirmeyi unutmayın.

#!/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"

5

Veritabanı dökümü oluşturmak için

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

Veritabanı dökümünü yeniden başlatmak için

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

5

Yalnızca pgadmin4 GUI (yedekleme ve geri yükleme yoluyla) kullanarak bir veritabanı üzerinde kopya oluşturma işlemi

Postgres Pgadmin4 ile birlikte gelir. MacOS kullanıyorsanız, CMD+ tuşuna basıp çalıştırmak için SPACEyazabilirsiniz pgadmin4. Bu, Chrome'da bir tarayıcı sekmesi açar.


Kopyalama adımları

1. Yedeği oluşturun

Bunu veritabanını sağ tıklatarak yapın -> "yedekleme"

resim açıklamasını buraya girin

2. Dosyaya bir ad verin.

Gibi test12345. Yedekle'yi tıklayın. Bu bir ikili dosya dökümü oluşturur, bir .sqlbiçimde değildir

resim açıklamasını buraya girin

3. Nereden indirildiğine bakın

Ekranınızın sağ alt köşesinde bir açılır pencere olmalıdır. Yedeklemenizin nereye indirildiğini görmek için "daha fazla ayrıntı" sayfasını tıklayın

resim açıklamasını buraya girin

4. İndirilen dosyanın konumunu bulun

Bu durumda, /users/vincenttang

resim açıklamasını buraya girin

5. Yedeklemeyi pgadmin'den geri yükleyin

1 ile 4 arasındaki adımları doğru yaptığınızı varsayarsak, bir geri yükleme ikili dosyasına sahip olursunuz. İş arkadaşınızın geri yükleme dosyanızı yerel makinelerinde kullanmak istediği bir zaman gelebilir. Dedi ki kişi pgadmin'e gidip geri döndü mü

Bunu veritabanını sağ tıklatarak yapın -> "geri yükle"

resim açıklamasını buraya girin

6. Dosya bulucuyu seçin

Dosya konumunu manuel olarak seçtiğinizden emin olun, pgadmin'deki yükleyici alanlarına dosya sürükleyip BIRAKMAYIN. Çünkü hata izinleriyle karşılaşacaksınız. Bunun yerine, az önce oluşturduğunuz dosyayı bulun:

resim açıklamasını buraya girin

7. Adı geçen dosyayı bul

Filtreyi en altta "Tüm dosyalar" olarak değiştirmeniz gerekebilir. Daha sonra, 4. adımdan itibaren dosyayı bulun. Şimdi onaylamak için sağ alttaki "Seç" düğmesine basın

resim açıklamasını buraya girin

8. Adı geçen dosyayı geri yükle

Dosyanın konumu seçiliyken bu sayfayı tekrar göreceksiniz. Devam et ve geri yükle

resim açıklamasını buraya girin

9. Başarı

Her şey yolundaysa, sağ alttaki başarılı bir geri yüklemeyi gösteren bir gösterge açılır. Verilerin her tabloda düzgün bir şekilde geri yüklenip yüklenmediğini görmek için tablolarınıza gidebilirsiniz.

10. Başarılı olamadıysa:

9. adımın başarısız olması durumunda, veritabanınızdaki eski genel şemanızı silmeyi deneyin. "Sorgu Aracı" na gidin

resim açıklamasını buraya girin

Bu kod bloğunu yürütün:

DROP SCHEMA public CASCADE; CREATE SCHEMA public;

resim açıklamasını buraya girin

Şimdi 5. ila 9. adımları tekrar deneyin.

DÜZENLE - Bazı ek notlar. Yükleme sırasında "arşivleyici başlığı 1.14 desteklenmeyen sürüm" satırlarında bir şeyle ilgili bir hata alıyorsanız PGADMIN4'ü güncelleyin


3

Veritabanında açık bağlantılar varsa, bu komut dosyası yardımcı olabilir. Bunu her gece canlı prodüksiyon veritabanının yedeğinden bir test veritabanı oluşturmak için kullanıyorum. Bu üretim db bir .SQL yedekleme dosyası olduğunu varsayar (Bunu webmin içinde yapmak).

#!/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"

1

PgAdmin kullanarak, şablon olarak kullanmak istediğiniz veritabanının bağlantısını kesin. Sonra yeni veritabanı oluşturmak için şablon olarak seçin, bu zaten kullanım hatası almaktan kaçınır.


0

Tüm şemayı kopyalamak istiyorsanız, aşağıdaki komutla bir pg_dump yapabilirsiniz:

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

Ve bu dökümü içe aktarmak istediğinizde şunları kullanabilirsiniz:

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

Bağlantı dizeleri hakkında daha fazla bilgi: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING

Ya da sadece bir astarda birleştirin:

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”

0
  1. Ana Pencereyi pgAdmin'de açın ve sonra başka bir Sorgu Araçları Penceresi açın
  2. PgAdmin'deki ana pencerelerde,

Şablon olarak kullanmak istediğiniz "templated" veritabanının bağlantısını kesin.

  1. Sorgu Araçları Penceresine Git

Aşağıdaki gibi 2 sorgu çalıştırın

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

(Yukarıdaki SQL ifadesi, TemplateDB ile tüm etkin oturumları sonlandıracak ve daha sonra yeni TargetDB veritabanını oluşturmak için şablon olarak seçebilirsiniz, bu zaten kullanım hatasını almayı önler.)

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

-4

Bunu dene:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.