Создание копии базы данных в PostgreSQL

730

Как правильно скопировать всю базу данных (ее структуру и данные) в новую в pgAdmin?

egaga
источник

Ответы:

1121

Postgres позволяет использовать любую существующую базу данных на сервере в качестве шаблона при создании новой базы данных. Я не уверен, дает ли pgAdmin опцию в диалоговом окне создания базы данных, но вы должны иметь возможность выполнить следующее в окне запроса, если это не так:

CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;

Тем не менее, вы можете получить:

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

Чтобы отключить всех других пользователей от базы данных, вы можете использовать этот запрос:

SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity 
WHERE pg_stat_activity.datname = 'originaldb' AND pid <> pg_backend_pid();
колокол
источник
68
Обратите внимание, что originaldb должен быть бездействующим (без транзакций записи), чтобы это работало.
synecdoche
62
в pgAdmin3 на панели обозревателя объектов (слева) я могу выбрать Servers-> (мой сервер) -> Databases, щелкнуть правой кнопкой мыши Базы данных и выбрать «Новая база данных». Одним из вариантов является шаблон, а SQL, используемый для создания базы данных, эквивалентен. Это так гораздо быстрее , чем свалка / восстановления на том же сервере.
jwhitlock
22
Я знаю, что это старый Q / A, но я чувствую, что это требует уточнения: когда @synecdoche говорит, что originaldb должен быть бездействующим, это означает, что вообще нет возможности записи. «Копирование» базы данных таким способом не блокирует originaldb. PostgreSQL запрещает запуск копирования только в том случае, если есть другие, которые обращаются к originaldb - не после начала копирования, поэтому возможно, что другое соединение может изменить базу данных, пока происходит «копирование». ИМХО, это может быть самый простой ответ, но «лучшим» будет использование dump / restore.
Джош
10
Я только что видел это. @Josh: пока исходная база данных копируется с помощью создания базы данных с шаблоном, postgresql не позволяет создавать новое подключение к нему, поэтому изменения невозможны.
ceteras
4
Обратите внимание, что если вы используете pgAdmin и выполняете CREATE DATABASE ... TEMPLATE xxx из командного окна SQL, вы должны отключиться от базы данных в главном окне pgAdmin, иначе вы получите сообщение об ошибке, связанное с пользователями, подключенными к базе данных.
Джек Р.Г.
296

Версия ответа Белла для командной строки :

createdb -O ownername -T originaldb newdb

Это должно выполняться под привилегиями хозяина базы данных, обычно postgres.

Zbyszek
источник
5
Это хорошая команда, НО вы получите, createdb: database creation failed: ERROR: source database "conf" is being accessed by other usersесли попытаетесь сделать это в производственной базе данных, и, как ожидается, вы не захотите выключать ее для создания копии.
Сорин
7
Да, к этой команде применяются те же предостережения, что и к явному вызову CREATE DATABASE. Как сказано в комментариях к ответу Белла, база данных должна быть бездействующей.
zbyszek
108

Чтобы клонировать существующую базу данных с помощью postgres, вы можете сделать это

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

IT прервет все соединения с исходной БД, избегая ошибки

ERROR:  source database "SOURCE_DB" is being accessed by other users
Brugolo
источник
7
+1 за упоминание решения сценария, чтобы избежать ошибки доступа
хулиган
14
На Postgres 9.2 я должен заменить procpidс pidдля этой работы
marxjohnson
75

В производственной среде, где исходная база данных находится под трафиком, я просто использую:

pg_dump production-db | psql test-db
Tregoreg
источник
8
Одна проблема, с которой я столкнулся при использовании этого метода, заключается в том, что pg_dump будет держать свою транзакцию открытой до тех пор, пока восстановление в новую базу данных не будет завершено, даже если pg_dump фактически завершит свой дамп. В некоторых случаях это может вызвать проблемы с блокировкой (например, если в исходной БД выполняется инструкция DDL).
Крис Батлер
3
Плюс один за неиспользование временных промежуточных файлов.
Арди Арам
Это было и мое решение. Вчера это сработало, теперь случайные уникальные ограничения нарушены. Примечание: я опускаю всю таблицу в базу данных получателя.
gunzapper
1
@AlexanderMills pg_dump -s? postgresql.org/docs/current/static/app-pgdump.html
Трегорег,
1
Это предполагает, что test-db существует. В противном случае создайте новый БД с$ createdb newdb
SamGoody
50

Не знаю насчет pgAdmin, но pgdumpвыдает дамп базы данных в SQL. Вам нужно только создать базу данных с тем же именем и сделать

psql mydatabase < my dump

восстановить все таблицы и их данные и все права доступа.

TrayMan
источник
Спасибо, что мне нужно , чтобы создать дамп с другого сервера, и, кажется , что это помогает: postgresql.org/docs/8.3/interactive/...
egaga
19
Вы даже можете это сделать, pg_dump -U postgres sourcedb | psql -U postgres newdbхотя эффективность этой техники может быть сомнительной (поскольку вы, вероятно, в конечном итоге переключаетесь между чтением и записью контекста)
Фрэнк Фармер,
1
Вы даже можете получить свой дамп с удаленной машины через ssh: ssh dbserver pg_dump DBNAME | psql NEWDB... или pg_dump DBNAME | ssh otherserver pgsql NEWDB ... Разрешения и аутентификация, конечно, должны быть обработаны, однако вы хотите обрабатывать их.
гхоти
23

Во-первых, sudoкак пользователь базы данных:

sudo su postgres

Перейдите в командную строку PostgreSQL:

psql

Создайте новую базу данных, дайте права и выйдите:

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

Скопируйте структуру и данные из старой базы данных в новую:

pg_dump old_database_name | psql new_database_name
Матье Родик
источник
Как убедиться, что все в порядке, даже некоторые ошибки (проблемы с сетью) произошли? Как проверить, совпадают ли две базы данных после миграции?
BAE
Ошибки должны отображаться в терминале всякий раз, когда они встречаются. Две базы данных должны быть одинаковыми после операции. Тем не менее, я не знаю, как это проверить ...
Матье Родич
2
Работает как шарм, я сделал это, пока база данных была в производстве.
BioRod
Это, кажется, работает хорошо; однако две базы данных имеют разный размер диска через \l+. Почему разница в размерах?
Косгеинский
@kosgeinsky на этот вопрос подробно ответили здесь: dba.stackexchange.com/a/102089/39386
Матье Родич,
18

Я собрал этот подход вместе с примерами сверху. Я работаю на сервере "под нагрузкой" и получил ошибку, когда попытался подойти от @zbyszek. Я также был после решения "только для командной строки".

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

Вот что сработало для меня ( Команды с префиксом nohupдля перемещения вывода в файл и защиты от отключения сервера ):

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

    мой пользователь "postgres"

  3. nohup psql exampledbclone_01 < example-01.sql

fusion27
источник
15

В pgAdmin вы можете сделать резервную копию из вашей исходной базы данных, а затем просто создать новую базу данных и восстановить из только что созданной резервной копии:

  1. Щелкните правой кнопкой мыши исходную базу данных, Backup ... и дамп в файл.
  2. Щелкните правой кнопкой мыши, Новый объект, Новая база данных ... и назовите пункт назначения.
  3. Щелкните правой кнопкой мыши новую базу данных, Восстановите ... и выберите свой файл.
Isomorph
источник
Я связал таблицы через внешние ключи, и это работало просто отлично.
Рэндалл Блейк
12

Как правильно скопировать всю базу данных (ее структуру и данные) в новую в pgAdmin?

Ответ:

CREATE DATABASE newdb WITH TEMPLATE originaldb;

Пробовал и проверял.

Анирбан Чакрабарти
источник
3
Это требует, чтобы originaldb не использовался. Метод Изоморфа нет.
Брэдли
2
Тот же самый ответ был дан почти за три года до твоего
Джейсон С.
8

Из документации использование createdbили CREATE DATABASEс шаблонами не рекомендуется:

Хотя можно скопировать базу данных, отличную от template1, указав ее имя в качестве шаблона, это (пока) не предназначено для универсального средства «КОПИРОВАНИЕ БАЗЫ ДАННЫХ». Основным ограничением является то, что никакие другие сеансы не могут быть подключены к базе данных шаблонов во время ее копирования. CREATE DATABASE потерпит неудачу, если при запуске будет какое-либо другое соединение; в противном случае новые подключения к базе данных шаблонов блокируются до завершения CREATE DATABASE.

pg_dump или pg_dumpall это хороший способ скопировать базу данных и все данные. Если вы используете графический интерфейс, такой как pgAdmin, эти команды вызываются негласно, когда вы выполняете команду резервного копирования. Копирование в новую базу данных выполняется в два этапа: резервное копирование и восстановление

pg_dumpallсохраняет все базы данных в кластере PostgreSQL. Недостаток этого подхода заключается в том, что в итоге вы получаете потенциально очень большой текстовый файл, полный SQL, необходимый для создания базы данных и заполнения данных. Преимущество этого подхода заключается в том, что вы получаете все роли (разрешения) для кластера бесплатно. Чтобы сбросить все базы данных, сделайте это из учетной записи суперпользователя

pg_dumpall > db.out

и восстановить

psql -f db.out postgres

pg_dumpимеет некоторые параметры сжатия, которые дают вам файлы меньшего размера. У меня есть производственная база данных, которую я делаю резервное копирование два раза в день с помощью cron, используя

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

где compressуровень сжатия (от 0 до 9) и createуказывает pg_dumpна добавление команд для создания базы данных. Восстановите (или переместите в новый кластер), используя

pg_restore -d newdb db.dump

где newdb - это имя базы данных, которую вы хотите использовать.

Другие вещи, чтобы думать о

PostgreSQL использует ROLES для управления разрешениями. Они не копируются pg_dump. Кроме того, мы не имели дело с настройками в postgresql.conf и pg_hba.conf (если вы перемещаете базу данных на другой сервер). Вы должны будете самостоятельно определить настройки conf. Но есть одна уловка, которую я только что обнаружил для резервного копирования ролей. Роли управляются на уровне кластера, и вы можете запросить pg_dumpallрезервное копирование только ролей с помощью --roles-onlyпереключателя командной строки.

bfris
источник
7

PostgreSQL 9.1.2:

$ CREATEDB new_db_name -T orig_db_name -O db_user;
Арта
источник
3
Вероятно, это реализовано, CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;и в результате требуется, чтобы исходная база данных находилась в режиме ожидания (без соединений с доступом для записи), и любые новые соединения с исходной базой данных не допускаются во время копирования. Если вы довольны этим, это работает.
Микко Ранталайнен
Хорошая деталь. Спасибо!
Арта
6

Для тех, кто все еще заинтересован, я разработал скрипт bash, который делает (более или менее) то, что хотел автор. Мне приходилось делать ежедневную бизнес-копию базы данных в производственной системе, этот скрипт, похоже, помогает. Не забудьте изменить имя базы данных / значения пользователя / 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"
Дариуш
источник
5

Создать дамп базы данных

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

Чтобы восстановить дамп базы данных

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

Вот весь процесс создания копии базы данных с использованием только графического интерфейса pgadmin4 (с помощью резервного копирования и восстановления)

Postgres поставляется с Pgadmin4. Если вы используете macOS, вы можете нажать CMD+ SPACEи набрать, pgadmin4чтобы запустить его. Это откроет вкладку браузера в Chrome.


Шаги для копирования

1. Создайте резервную копию

Сделайте это, щелкнув правой кнопкой мыши базу данных -> «резервное копирование»

введите описание изображения здесь

2. Дайте файлу имя.

Как test12345. Нажмите кнопку резервного копирования. Это создает дамп двоичного файла, он не в .sqlформате

введите описание изображения здесь

3. Посмотрите, где он скачал

Там должно быть всплывающее окно в нижней части экрана. Нажмите на страницу «подробнее», чтобы увидеть, куда была загружена ваша резервная копия

введите описание изображения здесь

4. Найдите местоположение загруженного файла

В этом случае это /users/vincenttang

введите описание изображения здесь

5. Восстановите резервную копию из pgadmin

Если вы правильно выполнили шаги с 1 по 4, у вас будет восстановленный двоичный файл. Может случиться, что ваш коллега захочет использовать ваш файл восстановления на своей локальной машине. Сказал ли человек пойти в пгадмин и восстановить

Сделайте это, щелкнув правой кнопкой мыши базу данных -> «восстановить»

введите описание изображения здесь

6. Выберите поиск файлов

Убедитесь, что вы выбрали местоположение файла вручную, НЕ перетаскивайте файл в поля загрузки в pgadmin. Потому что вы столкнетесь с ошибками разрешений. Вместо этого найдите файл, который вы только что создали:

введите описание изображения здесь

7. Найти указанный файл

Возможно, вам придется изменить фильтр внизу на «Все файлы». Затем найдите файл, начиная с шага 4. Теперь нажмите правую нижнюю кнопку «Выбрать», чтобы подтвердить

введите описание изображения здесь

8. Восстановить указанный файл

Вы снова увидите эту страницу с выбранным местоположением файла. Идите вперед и восстановите его

введите описание изображения здесь

9. Успех

Если все хорошо, в правом нижнем углу должен появиться индикатор, показывающий успешное восстановление. Вы можете перейти к своим таблицам, чтобы увидеть, были ли данные восстановлены надлежащим образом в каждой таблице.

10. Если это не удалось:

В случае сбоя шага 9 попробуйте удалить старую общедоступную схему в вашей базе данных. Перейти к «Инструменту запроса»

введите описание изображения здесь

Выполните этот блок кода:

DROP SCHEMA public CASCADE; CREATE SCHEMA public;

введите описание изображения здесь

Теперь повторите шаги с 5 по 9, это должно сработать

РЕДАКТИРОВАТЬ - Некоторые дополнительные заметки. Обновите PGADMIN4, если во время загрузки вы получили ошибку, указав что-то вроде «архиватор header 1.14 неподдерживаемая версия» во время восстановления

Винсент Тан
источник
3

Если база данных имеет открытые соединения, этот скрипт может помочь. Я использую это для создания тестовой базы данных из резервной копии рабочей базы данных каждую ночь. Это предполагает, что у вас есть файл резервной копии .SQL из производственной базы данных (я делаю это в 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"
screig
источник
1

Используя pgAdmin, отключите базу данных, которую вы хотите использовать в качестве шаблона. Затем вы выбираете его в качестве шаблона для создания новой базы данных, это позволяет избежать появления ошибки уже используется.

evergreener2
источник
0

Если вы хотите скопировать всю схему, вы можете создать pg_dump с помощью следующей команды:

pg_dump -h database.host.com -d database_name -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" -f sql_dump_to_import.sql

Больше информации о строках соединения: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING.

Или просто объединить его в один лайнер:

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. Откройте главное окно в pgAdmin, а затем откройте другое окно инструментов запросов.
  2. В основных окнах в pgAdmin,

Отключите «шаблонную» базу данных, которую вы хотите использовать в качестве шаблона.

  1. Перейти к окну инструментов запроса

Запустите 2 запроса, как показано ниже

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

(Приведенный выше оператор SQL завершит все активные сеансы с TemplateDB, а затем вы можете выбрать его в качестве шаблона для создания новой базы данных TargetDB, это позволит избежать появления ошибки, уже используемой.)

CREATE DATABASE 'TargetDB'
  WITH TEMPLATE='TemplateDB'
       CONNECTION LIMIT=-1;
titushui
источник
-4

Попробуй это:

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;

гл XD

user3108031
источник