如何将Postgres数据库恢复到另一个数据库名称

45

今天我使用了Postgres,并遇到了一个问题。我是这样转储数据库的:

 pg_dump zeus_development -U test > zeus_development.dump.out

如果我想还原到另一个名为zeus_production的数据库,该怎么办?

我应该如何操作?


3
附注 - 使用二进制转储格式之一可能比使用纯文本更好。它将加快转储/还原过程,减小转储文件的大小,并提供一些额外的方法来控制还原过程。详情在此 - Ihor Romanchenko
7个回答

48

首先,使用template0作为你的模板数据库创建你的数据库:

createdb -U test -T template0 zeus_production

然后,在该数据库上恢复您的转储:

psql -U test zeus_production -f /path/to/zeus_development.dump.out

在恢复数据库时,始终明确使用template0,因为它始终是一个空的、不可修改的数据库。如果您不使用明确的模板,则PostgreSQL将假定template1,如果它具有一些对象(如已经存在于您转储的数据库中的表或函数),则在恢复过程中会出现一些错误。

尽管如此,即使您在具有相同名称(zeus_development)的数据库上进行恢复,也应以相同的方式创建(或重新创建)它。除非您在转储时使用了-C选项(或者如果使用二进制转储,则使用pg_restore-C选项),但我不建议这样做,因为这将给您带来较少的灵活性(例如在不同的数据库名称上进行恢复)。


28

PostgreSQL文档影响了我使用自定义格式。我已经使用它多年,它似乎有各种优点,但你可能会有所不同。话虽如此,这是对我有用的方法:

pg_restore --no-owner --dbname postgres --create ~/Desktop/pg_dump 
psql --dbname postgres -c 'ALTER DATABASE foodog_production RENAME TO foodog_development'

在这个序列之前,不存在foodog_development或者foodog_production数据库。

这将从转储文件(~/Desktop/pg_dump)中恢复数据库,并以被转储时的名称创建它。重命名命名了数据库为您想要的任何名称。

如果两台机器上使用相同的用户名,则可能不需要使用--no-owner选项。在我的情况下,转储使用的是user1,恢复操作使用的是user2。新对象需要属于user2,并且--no-owner可实现此目的。


4
我通常使用自定义格式,因为文本格式在还原时经常失败。这个答案对我来说非常有用。 - code_monk

7

直接这样做不是更简单吗?

createdb -U test -T zeus_development zeus_production

实际上,上面的代码确实有效。原始问题并没有提到他要移动到新机器上,这只是假设。-T 选项非常强大。 - pedz
太好了。这为我节省了很多时间。简单易懂。 - M46
这不会占用双倍的磁盘空间吗? - Ken Ratanachai S.
如果将数据从A机器导出,然后在B机器上进行恢复,这个过程是如何执行的? - Chris F

6

这个问题在dba.stackexchange上有一个答案,我在这里复制如下:

我们定义一些变量,以使其余部分更易于复制/粘贴。

old_db=my_old_database
new_db=new_database_name
db_dump_file=backups/my_old_database.dump
user=postgres

以下假设您的备份是使用以下“自定义”格式创建的:
pg_dump -U $user -F custom $old_db > "$db_dump_file"

将数据库备份文件 $db_dump_file 还原到新的数据库名称 $new_db

dropdb   -U $user --if-exists  $new_db
createdb -U $user -T template0 $new_db

pg_restore -U $user -d $new_db "$db_dump_file"

3

如果您的转储文件中不包含名称,则还原将使用在DESTINATION中定义的数据库。 SOURCEDESTINATION都是连接URL

不带--create的转储文件

pg_dump \
  --clean --if-exists \
  --file ${dump_path} \
  --format=directory \
  --jobs 5 \
  --no-acl \
  --no-owner \
  ${SOURCE}

不使用--create进行还原

pg_restore \
  --clean --if-exists \
  --dbname=${DESTINATION} \
  --format=directory \
  --jobs=5 \
  --no-acl \
  --no-owner \
  $dump_path

这个操作非常顺利,没有出现任何外键或其他问题,完全不像我使用psql和文本转储时那样。谢谢! - undefined

1
感谢@mmel的回答。但是我将它调整了一下,这是适合我的方法:
垃圾桶:
pg_dump \
  --file {filename}.tar \
  --format=tar \
  --no-acl \
  --no-owner \
  --no-privileges \
  -U {username} \
  -h {host} \
  -p {port} \
  {db-name}

恢复:
pg_restore \
  --format=tar \
  --no-acl \
  --no-owner \
  --no-privileges \
  -U {username} \
  -h {host} \
  -p {port} \
  {db-name}
  {same-filename-as-dump}.tar


0
这是一种“hacky”的方法,只有在您可以承受使用常规的.sql格式的空间和时间,并且可以安全地使用sed删除数据库名称和用户时才有效。
$ pg_dump -U my_production_user -h localhost my_production > my_prod_dump.sql
$ sed -i 's/my_production_user/my_staging_user/g' my_prod_dump.sql
$ sed -i 's/my_production/my_staging/g' my_prod_dump.sql
$ mv my_prod_dump.sql my_staging_dump.sql

$ sudo su postgres -c psql
psql> drop database my_staging;
psql> create database my_staging owner my_staging_user;
psql> \c my_staging;
psql> \i my_staging_dump.sql

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接