在PostgreSQL中创建数据库的副本

ega*_*aga 693 postgresql

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

Bel*_*ell 1073

Postgres允许在创建新数据库时将服务器上的任何现有数据库用作模板.我不确定pgAdmin是否在create database对话框中为您提供了选项,但如果不是,您应该能够在查询窗口中执行以下操作:

CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;
Run Code Online (Sandbox Code Playgroud)

不过,你可能会得到:

ERROR:  source database "originaldb" is being accessed by other users
Run Code Online (Sandbox Code Playgroud)

要修复它,您可以使用此查询

SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity 
WHERE pg_stat_activity.datname = 'originaldb' AND pid <> pg_backend_pid();
Run Code Online (Sandbox Code Playgroud)

  • 请注意,originaldb需要空闲(没有写入事务)才能使其正常工作. (65认同)
  • 在pgAdmin3中,在对象浏览器(左)窗格中,我可以选择`Servers` - >*(我的服务器)* - >`Databases`,右键单击Databases,然后选择"New Database".其中一个选项是模板,用于创建数据库的SQL是等效的.它比同一服务器上的转储/恢复快得多*. (61认同)
  • 我知道这是一个旧的Q/A,但我觉得需要澄清:当@synecdoche说原始db必须是空闲时,这意味着根本没有写入可能性.以这种方式"复制"数据库不会锁定originaldb.如果有其他人访问originaldb,PostgreSQL只会阻止启动副本 - 不是在复制开始之后,因此在发生"复制"时,另一个连接可能会修改数据库.恕我直言,这可能是最简单的答案,但"最好的"将是使用转储/恢复. (22认同)
  • 我刚看到这个.@Josh:虽然createdb正在使用模板复制原始数据库,但postgresql不允许创建与它的新连接,因此不可能进行任何更改. (10认同)
  • 请注意,如果您正在使用pgAdmin并从SQL命令窗口执行CREATE DATABASE ... TEMPLATE xxx,则必须在主pgAdmin窗口中断开与数据库的连接,否则您将收到有关连接到数据库的用户的错误. (4认同)
  • 如果你得到这个错误("错误:源数据库......"),你可以通过执行这个查询来避免它:`SELECT pg_terminate_backend(pg_stat_activity.pid)FROM pg_stat_activity WHERE pg_stat_activity.datname ='originaldb'AND pid <> pg_backend_pid( ); ` (2认同)
  • 这不会复制像search_path这样的数据库设置吗?刚刚尝试过,我新创建的数据库只有默认的 search_path,尽管在原始(模板)数据库上使用 ALTER DATABASE 设置了它。 (2认同)

zby*_*zek 287

Bell的答案的命令行版本:

createdb -O ownername -T originaldb newdb
Run Code Online (Sandbox Code Playgroud)

这应该在数据库主机的权限下运行,通常是postgres.

  • 是的,对于此命令,同样的警告适用于显式CREATE DATABASE调用.就像Bell上面的回答所说的那样,数据库应该是空闲的. (7认同)
  • 这是一个很好的命令,但你会得到`createdb:数据库创建失败:错误:其他用户正在访问源数据库"conf"如果你试图在生产数据库上执行它并且按照预期你不想关闭它下来创建一个副本. (5认同)

Bru*_*olo 105

要使用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;
Run Code Online (Sandbox Code Playgroud)

IT将终止与源数据库的所有连接,避免错误

ERROR:  source database "SOURCE_DB" is being accessed by other users
Run Code Online (Sandbox Code Playgroud)

  • 在Postgres 9.2上我必须用'pid`替换`procpid`才能工作 (14认同)
  • +1提及脚本解决方案以避免访问错误 (7认同)

Tre*_*reg 72

在生产环境中,原始数据库处于流量中,我只是使用:

pg_dump production-db | psql test-db
Run Code Online (Sandbox Code Playgroud)

  • 我用这种方法发现的一个问题是pg_dump将保持打开它的事务,直到恢复到新数据库完成,即使pg_dump实际上已完成其转储.在某些情况下,这可能会导致锁定问题(例如,如果在源数据库上运行DDL语句). (7认同)
  • 另外一个不使用临时中间文件. (3认同)
  • @AlexanderMills `pg_dump -s`?https://www.postgresql.org/docs/current/static/app-pgdump.html (2认同)
  • 这假设存在 test-db。否则,使用 `$ createdb newdb` 创建新数据库 (2认同)

Tra*_*Man 49

不了解pgAdmin,但是pgdump在SQL中为您提供了数据库的转储.您只需要使用相同的名称创建数据库即可

psql mydatabase < my dump
Run Code Online (Sandbox Code Playgroud)

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

  • 你甚至可以做`pg_dump -U postgres sourcedb | psql -U postgres newdb`虽然这种技术的效率可能有问题(因为你可能最终在读取和写入之间切换上下文) (19认同)

Mat*_*dic 21

首先,sudo作为数据库用户:

sudo su postgres
Run Code Online (Sandbox Code Playgroud)

转到PostgreSQL命令行:

psql
Run Code Online (Sandbox Code Playgroud)

创建新数据库,授予权限并退出:

CREATE DATABASE new_database_name;
GRANT ALL PRIVILEGES ON DATABASE new_database_name TO my_user;
\d
Run Code Online (Sandbox Code Playgroud)

将结构和数据从旧数据库复制到新数据库:

pg_dump old_database_name | psql new_database_name
Run Code Online (Sandbox Code Playgroud)

  • 像魅力一样工作,我在数据库投入生产时做到了. (2认同)

fus*_*n27 16

我将这种方法与上面的例子拼凑在一起.我正在研究一个"欠载"服务器,当我从@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


小智 14

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

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


Vin*_*ang 11

这是仅使用 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;
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

现在再次尝试第 5 步到第 9 步,应该会成功

编辑- 一些附加说明。如果您在上传过程中遇到错误,请更新 PGADMIN4


小智 10

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

回答:

CREATE DATABASE newdb WITH TEMPLATE originaldb;
Run Code Online (Sandbox Code Playgroud)

试过并测试过.

  • 这要求originaldb不被使用.Isomorph的方法没有. (3认同)
  • 在您之前将近三年提供相同的答案 (2认同)

Art*_*rta 7

PostgreSQL 9.1.2:

$ CREATEDB new_db_name -T orig_db_name -O db_user;
Run Code Online (Sandbox Code Playgroud)

  • 这可能实现为`CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;`因此要求原始数据库必须处于空闲状态(没有与写访问的连接),并且在复制过程中会阻止与原始数据库的任何新连接.如果你对此感到满意,那就行了. (3认同)

Dar*_*usz 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"
Run Code Online (Sandbox Code Playgroud)


Jag*_*h N 5

创建数据库转储

cd /var/lib/pgsql/
pg_dump database_name> database_name.out
Run Code Online (Sandbox Code Playgroud)

重新发布数据库转储

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
Run Code Online (Sandbox Code Playgroud)


bfr*_*ris 5

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

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

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

pg_dumpall将所有数据库保存在PostgreSQL集群上。这种方法的缺点是最终可能会产生一个非常大的文本文件,其中包含创建数据库和填充数据所需的SQL。这种方法的优点是您可以免费获得群集的所有角色(权限)。要转储所有数据库,请从超级用户帐户执行此操作

pg_dumpall > db.out
Run Code Online (Sandbox Code Playgroud)

并还原

psql -f db.out postgres
Run Code Online (Sandbox Code Playgroud)

pg_dump有一些压缩选项,可以为您提供更小的文件。我有一个生产数据库,我每天使用cron作业备份两次

pg_dump --create --format=custom --compress=5 ==file=db.dump mydatabase
Run Code Online (Sandbox Code Playgroud)

compress压缩级别(0到9)在哪里,并create告诉pg_dump添加命令来创建数据库。通过使用还原(或移动到新群集)

pg_restore -d newdb db.dump
Run Code Online (Sandbox Code Playgroud)

其中,newdb是要使用的数据库的名称。

其他需要考虑的事情

PostgreSQL使用ROLES来管理权限。这些不会被复制pg_dump。另外,我们还没有处理postgresql.confpg_hba.conf中的设置(如果要将数据库移到另一台服务器上)。您必须自己弄清楚conf设置。但是我刚刚发现了一个备份角色的技巧。角色是在集群级别管理的,您可以要求pg_dumpall使用--roles-only命令行开关仅备份角色。