在PostgreSQL中创建数据库的副本


728

在pgAdmin中将整个数据库(其结构和数据)复制到新数据库的正确方法是什么?

Answers:


1120

创建新数据库时,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
请注意,origindb需要处于空闲状态(无写事务),此功能才能起作用。
synecdoche'5

62
在pgAdmin3中,在“对象浏览器”(左)窗格中,我可以选择Servers-> (我的服务器) -> Databases,右键单击“数据库”,然后选择“新建数据库”。选项之一是模板,用于创建数据库的SQL是等效的。它是这样比转储快得多/恢复在同一台服务器。
jwhitlock 2011年

22
我知道这是一个旧的Q / A,但是我觉得需要澄清:@synecdoche说originaldb必须是空闲的时,这意味着完全没有写入的可能性。以这种方式“复制”数据库不会锁定originaldb。PostgreSQL仅在有其他人访问originaldb的情况下才阻止启动副本-副本开始后不这样做,因此在“副本”发生时,另一个连接可能会修改数据库。恕我直言,这可能是最简单的答案,但“最佳”方法是使用转储/还原。
2012年

10
我刚刚看到了 @Josh:当createdb使用模板复制数据库时,postgresql不允许为其创建新连接,因此无法进行任何更改。
ceteras 2012年

4
请注意,如果您正在使用pgAdmin并从SQL命令窗口执行CREATE DATABASE ... TEMPLATE xxx,则必须在pgAdmin主窗口中断开与数据库的连接,否则会出现有关连接到数据库的用户的错误。
杰克RG 2014年

296

贝尔答案的命令行版本:

createdb -O ownername -T originaldb newdb

这应该在数据库主数据库(通常是postgres)的特权下运行。


5
这是一个很好的命令,但是createdb: database creation failed: ERROR: source database "conf" is being accessed by other users如果您尝试在生产数据库上执行此命令,并且您不希望关闭它以创建副本,则会得到该命令。
sorin 2012年

7
是的,此命令与显式CREATE DATABASE调用同样适用于此命令。就像上面对贝尔回答的评论所说,数据库应该是空闲的。
zbyszek'4

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

7
+1提及脚本解决方案以避免访问错误
欺负2014年

14
在Postgres的9.2我不得不更换procpidpid此工作
marxjohnson

75

在生产环境中,原始数据库处于繁忙状态,我只是在使用:

pg_dump production-db | psql test-db

8
我发现此方法的一个问题是,即使pg_dump实际上已经完成了其转储,pg_dump也会保持打开其事务直到还原到新数据库的操作完成。在某些情况下,这可能导致锁定问题(例如,如果在源DB上运行DDL语句)。
克里斯·巴特勒

3
再加上一个不使用临时中间文件的信息。
Ardee Aram 2015年

这也是我的解决方案。昨天它起作用了,现在违反了随机唯一约束。注意:我将所有表都删除到接收器数据库。
gunzapper '16


1
假设test-db存在。否则,请使用$ createdb newdb
SamGoody

50

不了解pgAdmin,但是pgdump可以使用SQL来转储数据库。您只需要用相同的名称创建数据库并执行

psql mydatabase < my dump

恢复所有表及其数据和所有访问权限。


谢谢,我需要从另一台服务器创建转储,似乎这有助于:postgresql.org/docs/8.3/interactive/...
egaga

19
pg_dump -U postgres sourcedb | psql -U postgres newdb尽管该技术的效率可能令人怀疑,但您甚至可以做(因为您可能最终会在读取和写入之间进行上下文切换)
Frank Farmer 2010年

1
您甚至可以通过ssh从远程计算机获取转储:ssh dbserver pg_dump DBNAME | psql NEWDB...或pg_dump DBNAME | ssh otherserver pgsql NEWDB ...当然需要处理权限和身份验证,但是您要处理它们。
ghoti 2012年

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

遇到错误时,应在终端中显示错误。操作后,两个数据库应该相同。但是,我不知道该如何检查...
Mathieu Rodic

2
工作起来就像一个魅力,我在数据库生产时就做到了。
BioRod

这似乎运作良好;但是,两个数据库的磁盘大小不同\l+。为什么尺寸不同?
kosgeinsky '19

@kosgeinsky,这在这里得到了广泛的回答:dba.stackexchange.com/a/102089/39386
Mathieu Rodic

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


15

在pgAdmin中,您可以从原始数据库进行备份,然后仅创建一个新数据库并从刚刚创建的备份进行还原:

  1. 右键单击源数据库,备份...,然后转储到文件。
  2. 右键单击,新建对象,新建数据库...,然后命名目标。
  3. 右键单击新数据库,还原...,然后选择文件。

我通过外键有相关的表,这很好用。
兰德尔·布雷克


8

文档开始,不建议使用createdbCREATE DATABASE与模板一起使用:

尽管可以通过将模板名称指定为模板来复制除template1之外的其他数据库,但是(尚未)将其用作通用的“ COPY DATABASE”工具。主要限制是,在复制模板数据库时,无法将其他会话连接到模板数据库。如果启动时存在任何其他连接,则CREATE DATABASE将失败。否则,将锁定与模板数据库的新连接,直到CREATE DATABASE完成。

pg_dump或者pg_dumpall是复制数据库和所有数据的好方法。如果使用的是pgAdmin之类的GUI,则在执行备份命令时会在后台调用这些命令。复制到新数据库分两个阶段完成:备份和还原

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.confpg_hba.conf中的设置(如果要将数据库移到另一台服务器上)。您必须自己弄清楚conf设置。但是我刚刚发现了一个备份角色的技巧。角色是在集群级别管理的,您可以要求pg_dumpall使用--roles-only命令行开关仅备份角色。


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;由于以下原因而实现的,因此,它要求原始数据库必须处于空闲状态(没有具有写访问权的连接),并且在复制过程中要防止与原始数据库的任何新连接。如果您对此感到满意,那就行得通。
Mikko Rantalainen 2013年

细节不错。谢谢!
阿尔塔

6

对于那些仍然感兴趣的人,我想出了一个bash脚本,可以(或多或少)执行作者想要的。我必须在生产系统上制作日常业务数据库副本,此脚本似乎可以解决问题。切记更改数据库名称/用户/密码值。

#!/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 GUI(通过备份和还原)在数据库上创建副本的整个过程。

Postgres带有Pgadmin4。如果您使用macOS,则可以按CMD+ SPACE并键入pgadmin4以运行它。这将在Chrome中打开一个浏览器标签。


复制步骤

1.创建备份

通过右键单击数据库->“备份”来执行此操作

在此处输入图片说明

2.给文件起一个名字。

test12345。单击备份。这将创建一个二进制文件转储,它不是.sql格式

在此处输入图片说明

3.查看下载位置

屏幕的右下角应该有一个弹出窗口。点击“更多详细信息”页面,查看备份下载到的位置

在此处输入图片说明

4.查找下载文件的位置

在这种情况下 /users/vincenttang

在此处输入图片说明

5.从pgadmin恢复备份

假设您正确执行了步骤1到步骤4,您将拥有一个还原二进制文件。有时您的同事希望在其本地计算机上使用您的还原文件。说过该人去pgadmin并恢复

通过右键单击数据库->“还原”来执行此操作

在此处输入图片说明

6.选择文件查找器

确保手动选择文件位置,请勿将文件拖放到pgadmin的上载器字段中。因为您会遇到错误权限。相反,找到您刚创建的文件:

在此处输入图片说明

7.找到所说的文件

您可能必须将右下角的过滤器更改为“所有文件”。此后,从第4步中查找文件。现在点击右下角的“选择”按钮以确认

在此处输入图片说明

8.恢复所说的文件

您将再次看到此页面,其中包含选定文件的位置。继续还原它

在此处输入图片说明

9.成功

如果一切正常,则右下角应弹出一个指示恢复成功的指示器。您可以导航到表以查看每个表上的数据是否已正确还原。

10.如果不成功:

如果第9步失败,请尝试删除数据库上的旧公共模式。转到“查询工具”

在此处输入图片说明

执行以下代码块:

DROP SCHEMA public CASCADE; CREATE SCHEMA public;

在此处输入图片说明

现在再次尝试步骤5到9,应该可以解决

编辑 -一些附加说明。如果在上传过程中出现错误,并在还原过程中出现“存档头1.14不支持的版本”的错误,请更新PGADMIN4


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"

1

使用pgAdmin,断开要用作模板的数据库的连接。然后,选择它作为创建新数据库的模板,这样可以避免出现已在使用中的错误。


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;

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

gl XD

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.