在不同主要版本的PostgreSQL之间使用pg_dump和pg_restore

36
我的开发机器(称为D)运行PostgreSQL 9.4.5。 我的生产机器(称为P)运行PostgreSQL 8.4.20。
我不使用PostgreSQL 9.x中的任何新功能或类型。
有时候我需要将P的状态镜像到D上,有时候则需要反过来。 在这两种情况下,我都使用pg_dump/pg_restore。
当我从P转储还原到D时,我从未遇到过任何错误或警告。 但是,当我尝试相反操作时,我会得到多个“不被识别的配置参数“lock_timeout”错误。 我知道这个配置参数是在9.3中引入的,并且由于恢复过程的其余部分工作正常,所以我只忽略了错误消息。
我的问题是:跨不同的主要版本使用pg_dump/pg_restore是否是一个不好的想法?或者可以像我一直在做的那样安全地忽略兼容性错误? 我将来会不会遇到问题? 我无法升级P,我应该将D降级到8.4.20以确保安全吗?
6个回答

15
根据PostgreSQL文档(https://www.postgresql.org/docs/14/app-pgdump.html)所述: 因为pg_dump用于将数据传输到更新的PostgreSQL版本,所以可以预期pg_dump的输出可以加载到比pg_dump版本更新的PostgreSQL服务器版本中。pg_dump还可以从其自身版本早于的PostgreSQL服务器转储。(目前,支持至版本8.0的服务器)。但是,pg_dump无法从其自身主要版本较新的PostgreSQL服务器中进行转储;它会拒绝尝试,而不是冒险制作无效的转储。此外,即使从该版本的服务器中获取了转储,也不能保证pg_dump的输出可以加载到较旧主要版本的服务器中。 因此,对于仍然有疑问的其他人来说,不能保证从PgSQL服务器较新版本得到的输出可以完全适用于旧版本。但相反的情况则可以正常工作。 建议是如果您的生产服务器与开发服务器不同,则至少应该较新。
关于忽略兼容性错误:

将转储文件加载到较旧的服务器上可能需要手动编辑转储文件,以删除较旧服务器不理解的语法。在跨版本情况下建议使用--quote-all-identifiers选项,因为它可以防止不同PostgreSQL版本中保留字列表不同而引起的问题。

最后一个建议是,如果您计划使软件长期运行,请考虑升级,因为旧版本将有一天过时。在提出这个问题时,PgSQL 8仍然有发布版本。现在你只能得到9.6的发布版本。


14
一般建议您使用适用于恢复版本的 pg_dump 工具。

当从旧版本迁移到新版本时,应使用更新的 pg_dump 工具。

有点烦人。

这取决于错误类型。您可以忽略此错误。

这取决于您的行为。显然,您不能忽略所有错误 - 例如,如果 CREATE TABLE 失败,您就会遇到麻烦。因此,这取决于所使用的功能等。

是的。 使用生产环境相同的版本进行开发。

不过,您需要尽快升级 P。 P已经不再支持,将不再获得进一步的漏洞修复,并且不会被打包到新的操作系统发布中,而且问题报告也会收到“升级到受支持的版本并查看是否仍然存在问题”的回复。


7
对于看到这个问题的人们:最好使用相同版本进行还原,但通常不太实际。
例如:我的本地开发机主要使用Postgres 12.1 (端口5433)来开发下一个版本。我还安装了Postgres 11 (端口5432),因为我们的生产和CI仍在使用Postgres 11。
所以我做了以下事情:
- 在 PG 12.1 中创建一个测试数据库 - 手动应用适用于 CI 中使用的示例数据的迁移脚本 - 使用 PG 12 pg_dump 导出并生成一个 dump 文件
"c:\Program Files\PostgreSQL\12\bin\pg_dump" -U postgres -p 5433 -d ut_20200621 --no-owner --no-acl "f:\dumps\ut_20200621_pg12.backup"
- 使用 PG 12 pg_restore 将此文件加载到 Postgres 11 中(与服务器不同的端口,但是版本相同)
"c:\Program Files\PostgreSQL\12\bin\pg_restore" -U postgres -p 5432 -d ut_20200621 --no-owner --no-acl "f:\dumps\ut_20200621_pg12.backup"
- 然后在 pg11 上创建一个 dump:请注意使用不同的版本
"c:\Program Files\PostgreSQL\11\bin\pg_restore" -U postgres -p 5432 -d ut_20200621 --no-owner --no-acl "f:\dumps\ut_20200621_pg12.backup"
然后我的 CI 服务器可以使用我手动创建的升级数据库。
对于发布版本,数据迁移是手动运行的:首先在预生产环境中运行,然后在生产环境中运行。

这是正确的答案!我一次又一次地发现自己需要依赖系统管理员来协调两台计算机之间的版本。因此,如果在原始机器上创建一个旧版本的测试数据库,@sknutsonsf的这个解决方案可以解决这个问题。 - superk

2

最重要的是保持工作流程:

创建备份

A. 使用--format=custom [-Fc]创建备份文件,以便使用pg_restore进行恢复。

## for pg_restore
pg_dump -v -Fc \
postgresql://<user>:<pass>@<host>:<port>/<dbname> \
> db-20211122-163508.sql

B. 如果版本不支持pg_restore(PostgreSQL 9.0.23),请删除-Fc并添加--clean [-c],然后使用psql进行恢复。

## for psql
pg_dump -v -c \
postgresql://<user>:<pass>@<host>:<port>/<dbname> \
> db-20211122-163508.sql

注意:现在,我们添加了一个连接字符串postgresql://<user>:<pass>@<host>:<port>/<dbname>,并用我们的真实信息替换了<user><pass><host><port><dbname>

恢复

A. 使用pg_restore恢复备份,我们将使用--clean [-c] 和 --create [-C] 在恢复之前删除数据库。

pg_restore -vcC \
-U <user> \
-h <host> \
-p <port> \
-d <dbname> \
< db-20211122-163508.sql

B. 使用 psql 恢复数据库时不需要任何特殊选项,只需记得在 pg_dump 命令中添加 --clean [-c] 选项。

psql -v \
-U <user> \
-h <host> \
-p <port> \
-d <dbname> \
< db-20211122-163508.sql

注意:现在,请用您的信息替换<user><host><port><dbname>


1

我的经验是从9.6还原转储到9.5.9。我使用第三个服务器9.5.13,将文件复制(最初创建备份)。

在服务器上用9.5.13替换文件:

/usr/share/postgresql-common/pg_wrapper

在9.5.13服务器上:
pg_restore -U $POSTGRES_USER -h localhost -d $POSTGRES_DB </tmp/dump.sql
创建转储:
pg_dump -U $POSTGRES_USER -h localhost -d $POSTGRES_DB -O -x > /tmp/dump_9_5_13.sql

在9.5.9服务器上:
psql -U $POSTGRES_USER -h localhost -d $POSTGRES_DB </tmp/dump_9_5_13.sql


0

日期:2022年11月22日

我做了以下工作,将数据从PG11迁移到PG14.5。

在PG11主机上:

- 修改pg_hba.conf以允许来自PG14.5主机的连接

- 重新加载postgresql

从PG14.5主机上:

- 使用pgsql14.5上的pg_dump转储pgsql11数据,并直接注入数据到pgsql14.5中

bash $ psql
postgres# create database <dbname> with owner <user> ;
ctrl+d
bash $ psql -U <user> -d <dbname> < <(pg_dump -v -c postgresql://<user>:<pass>@<host>:<port>/<dbname> )

几个小时前,它刚刚在一个dotnet-core6应用程序中完美地工作,但是当使用pgsql11 pg_dump命令将其旧数据库转储到PG11主机上并在PG14.5主机上使用pgsql14.5 psql命令还原时,它就无法正常工作了。


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