pg_restore: [archiver]在文件头中发现不支持的版本(1.14)。

71

我有一个正在运行PostgreSQL的生产服务器和开发环境,分别称为“live”和“dev”。我可以用pgadmin4看到并管理两者,而且两者都是完全可用的——一个是正在运行的网站,而另一个是我在我的开发环境中以调试模式运行网站的地方。这是非常普通的设置。

多年来,我一直在运行同样的bash脚本,该脚本会将实时数据库转储,然后在开发环境中还原它,以便我可以使用最新的实时快照。

今天,这个脚本无法正常运行,并显示了标题信息:

pg_restore: [archiver] unsupported version (1.14) in file header

我已经尝试过诊断,并在线上进行了广泛搜索,但是我一直陷入困境并失败了,因此我现在谦卑地请求专家的帮助。

为了帮助您更好地理解,我将分享以下内容:

$ pg_dump --version
pg_dump (PostgreSQL) 10.11 (Ubuntu 10.11-1.pgdg18.04+1)
$ pg_restore --version
pg_restore (PostgreSQL) 10.11 (Ubuntu 10.11-1.pgdg18.04+1)
$ pg_dump --host=live.lan --port=5432 --dbname=mydb --username=myuser --format=custom > test.backup
$ ls -l test.backup 
-rw-r--r-- 1 bernd bernd 2398358 Dec 23 23:40 test.backup
$ file test.backup 
test.backup: PostgreSQL custom database dump - v1.14-0
$ pg_restore --dbname=mydb test.backup 
pg_restore: [archiver] unsupported version (1.14) in file header

假设 pg_dump 和 pg_restore 是相同版本:

$ which pg_dump
/usr/bin/pg_dump
$ which pg_restore
/usr/bin/pg_restore
$ ls -l /usr/bin/pg_dump /usr/bin/pg_restore
lrwxrwxrwx 1 root root 37 Nov 14 23:23 /usr/bin/pg_dump -> ../share/postgresql-common/pg_wrapper
lrwxrwxrwx 1 root root 37 Nov 14 23:23 /usr/bin/pg_restore -> ../share/postgresql-common/pg_wrapper

我可以看到它们不仅仅是相同的版本,而且由同一个包装脚本运行(这个脚本碰巧是Perl脚本——现在你很少见到这种语言,但我曾经广泛编写过)

所以我完全感到困惑。考虑到实际机器上可能存在版本问题:

$ ssh live.lan
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-72-generic x86_64)
$ which pg_dump
/usr/bin/pg_dump
$ which pg_restore
/usr/bin/pg_restore
$ pg_dump --version
pg_dump (PostgreSQL) 10.10 (Ubuntu 10.10-0ubuntu0.18.04.1)
$ pg_restore --version
pg_restore (PostgreSQL) 10.10 (Ubuntu 10.10-0ubuntu0.18.04.1)

我可以看到现场盒子上的pg_dump版本比较老(只有在我的开发环境中的pg_dump以某种方式使用RPC来运行其pg_dump时才会有影响)。

现在,也许有一个小线索是因为我的开发环境已经通过了几次postgresql升级,例如:

$ pg_lsclusters
Ver Cluster Port Status Owner    Data directory              Log file
10  main    5432 online postgres /var/lib/postgresql/10/main /var/log/postgresql/postgresql-10-main.log
11  main    5433 online postgres /var/lib/postgresql/11/main /var/log/postgresql/postgresql-11-main.log
12  main    5434 online postgres /var/lib/postgresql/12/main /var/log/postgresql/postgresql-12-main.log

11 和 12 集群因为空日志文件而未被使用。 我正在使用10。 但我注意到:

$ psql --version
psql (PostgreSQL) 12.1 (Ubuntu 12.1-1.pgdg18.04+1)
$ ssh live.lan
Welcome to Ubuntu 18.04.3 LTS (GNU/Linux 4.15.0-72-generic x86_64)
$ psql --version
psql (PostgreSQL) 10.10 (Ubuntu 10.10-0ubuntu0.18.04.1)

这有点可疑,但并不明显是因果相关:

  1. 我正在使用 pg_dump 而不是 psql
  2. 我只使用 dev boxes 的 pg 工具而不是 live boxes(它们应该是无关紧要的,整个数据传输理论上都在端口 5432 上进行,live box 向我的 dev box 交付数据库转储)。

这是 love box 上的集群,并且我正在 live.lan 上通过端口 5432 运行 pg_dump!

$ pg_lsclusters 
Ver Cluster Port Status Owner    Data directory           Log file
10  main    5432 online postgres /data/postgresql/10/main /var/log/postgresql/postgresql-10-main.log

我目前对此感到深深困惑和束手无策。非常感激任何有助于解决问题的线索。如果我被迫在黑暗中寻找,我可能会再次卸载Postgres 11和12,看看是否有帮助;否则,我将不得不跟踪/usr/share/postgresql-common/pg_wrapper,查看pg_dump和pg_restore两个路径如何分叉到不兼容版本路径。

更新:

我发现了一个进一步的线索,这让我有了一个解决方法,但也增加了谜团:

$ sudo -u postgres pg_dump --host=live.lan --port=5432 --dbname=mydb --username=myuser --format=custom > test.backup
$ sudo -u postgres /usr/lib/postgresql/10/bin/pg_dump --host=live.lan --port=5432 --dbname=mydb --username=myuser --format=custom > test2.backup
$ sudo -u postgres pg_restore -l test.backup
pg_restore: [archiver] unsupported version (1.14) in file header
$ sudo -u postgres pg_restore -l test2.backup
... produces listing of contents ...
$ sudo -u postgres pg_dump --version
pg_dump (PostgreSQL) 10.11 (Ubuntu 10.11-1.pgdg18.04+1)
$ sudo -u postgres /usr/lib/postgresql/10/bin/pg_dump --version
pg_dump (PostgreSQL) 10.11 (Ubuntu 10.11-1.pgdg18.04+1)
那是令人难以置信的困惑。唯一可能的解释是:
  1. 尽管报告相同的版本号,但两个pg_dumps是不同的。我会认为这是不可思议的。
  2. pg_dump运行pg_wrapper,pg_wrapper使用某些神秘参数运行 /usr/lib/postgresql/10/bin/pg_dump 使其崩溃!
第二种可能性是很有道理的,我需要对pg_wrapper进行诊断。 更新2: 经过对pg_wrapper的一次检查,结果发现pg_dump运行pg_wrapper,pg_wrapper运行 /usr/lib/postgresql/12/bin/pg_dump,但实际运行的却是 /usr/lib/postgresql/10/bin/pg_restore... 真是匪夷所思!我开始认为这是postgresql版本互操作性的一个bug! 更新3: 进一步检查了pg_wrapper后,找到了原因。我认为这是pg_wrapper的一个bug,虽然这可能有争议,但在我看来根本就不是。以下是它的操作方式:
  • 如果提供了 --host,则使用已安装的最新版本的postgresql(在我的情况下为12,且这是针对pg_dump的,因此pg_dump 12创建了转储文件);
  • 如果未提供 --host,则会查阅用户配置(在我的情况下为10,这是针对pg_restore的,因此运行pg_restore 10,但它无法读取由pg_dump 12创建的文件)。
那么为什么这是一个bug呢?因为我有一个用户配置,并希望它得到尊重,无论我是否与远程主机通信。更重要的是,如果我指定了主机,我当然不希望使用最新的本地版本忽略本地配置。我期望要么遵循本地配置(当未指定远程主机时情况就是如此),要么尝试匹配远程主机的版本。在我看来,任意倾向于最新安装版本是非常可疑的。 但是,事实证明有一种有效的解决方法。基本上,不是:
sudo -u postgres pg_restore -l test.backup

这个有效:

sudo -u postgres pg_restore --host=localhost -l test.backup

通过具体指定主机,我们可以让它忽略本地配置,并使用最新版本的pg_restore工具,这似乎能够很好地恢复到PG 10集群。


开始认为这是一个postgresql版本互操作性的bug!听起来更像是一个打包错误。 - jjanes
1
@BerndWechner 我使用了以下命令:sudo -u postgres pg_restore --verbose --clean --jobs=4 --disable-triggers --no-acl --no-owner -h localhost -U postgresql -d everest_development dump.psql,但是它没有起作用。我在导入一个数据库时也遇到了同样的错误。 - LearningROR
如果我执行以下命令:muhammad@muhammad-mohsin:~/workspace_ror/everest$ psql -d everest_development -f dump.psql,那么输入的内容是一个PostgreSQL自定义格式的转储文件。请使用pg_restore命令行客户端将此转储文件恢复到数据库中。 - LearningROR
3
不确定有什么“解决方案”,但我发布了一个解决方法。在我的想法中,不同之处在于它可以工作,但不应该需要,pg_wrapper应该比它更聪明。解决方法很简单,只需在使用pg_dumppg_restore时明确指定--host,这会强制它们使用相同版本的postgresql(您系统上安装的最新版本)并保持兼容性。如果您在其中一台计算机上使用了--host而在另一台计算机上未使用,并且有多个版本的postgresql已安装并且早期版本仍在本地配置中使用,则会出现忘记此问题的情况。 - Bernd Wechner
如果您使用的是Windows操作系统,只需下载最新版本的pg admin即可。 - silvedo
显示剩余3条评论
7个回答

18

Ubuntu用户注意:您的pg_restore很可能已经过时。只需使用postgres文档并安装最新版本的postgres:

  1. 创建文件/etc/apt/sources.list.d/pgdg.list,并添加一个库的行:deb http://apt.postgresql.org/pub/repos/apt/ YOUR_UBUNTU_VERSION_HERE-pgdg main 其中ubuntu版本为:

    • 20.04 - focal
    • 18.04 - bionic
    • 16.04 - xenial
  2. 添加密钥:wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -

  3. sudo apt-get update && sudo apt-get upgrade

这对我起作用了!


中文:E: 'http://apt.postgresql.org/pub/repos/apt bionic-pgdg Release' 的存储库不再具有 Release 文件。 - undefined
你会认为Postgres可以更清楚地表达,而不是返回一个没有被任何Postgres版本使用的毫无意义的版本号... - undefined

9

我的经历与OP有些相似,但并非完全相同。

我安装了版本9.4、9.5、11和12,并且所有的pg_*工具都指向9.4版本。我试图在不同的主机上使用版本12创建的dump进行pg_restore,但由于该主机使用的是不兼容的9.4工具(与OP发布的相同错误),因此这种尝试失败了。

那么,以下是我的调试流程:

  • which pg_restore
    • /usr/bin/pg_restore
  • ls -l /usr/bin/pg_restore
    • /usr/bin/pg_restore -> ../share/postgresql-common/pg_wrapper
  • vim /usr/share/postgresql-common/pg_wrapper
    • 阅读它如何确定版本。只需阅读前20行左右即可

显然,有一个--cluster选项,有助于解决版本问题。因此,我只需在我的pg_restore调用中添加--cluster 12/main,一切又恢复正常了。


1
在https://render.com/docs/migrate-from-heroku上的说明没有生效,直到我添加了--cluster参数为止。将--cluster [version#]/main添加到pg_restore命令中帮助我将Heroku创建的pg_dump文件复制到Render.com的Postgres服务中。转储文件是使用Postgres版本15创建的。尽管psql已升级到版本15(仍在解决此问题),但我的AWS EC2实例上的pg_restore被锁定在版本10.23上,因此由于版本不匹配,Render.com上的Postgres服务无法读取该文件。 - mcmaddox
添加--cluster标志只会生成以下错误:pg_restore: 无法识别的选项 --cluster'`。 - undefined

5

注意,以下内容是关于Windows的。如果你只使用Linux,请不要继续阅读。

所有给出的建议都无法帮助我解决问题,最终原因很简单,与使用pgAdmin有关。由于一直提示更新,我习惯于单独安装pgAdmin(而不是使用stackbuilder)。

在这种情况下,pgAdmin有它自己的实用程序缓存,并且会使用这些实用程序,除非您告诉它不要这样做。我的pg实例仍然是11(.6)版本,但最新的pgAdmin可能会有V12实用程序。这可能会引起版本不兼容问题。

这个问题在我将许多文件从我的主机传输到笔记本电脑后才浮现出来。所以,在pgAdmin中进行以下操作:(菜单) 文件->首选项->路径,并设置与您的postgres安装相对应的二进制路径,IMC C:\Program Files\PostgreSQL\11\bin。

就这样解决了。


2

检查并确认您的pgadmin是否是最新版本,我曾经遇到过这个问题,通过更新它来解决了这个问题。


1
这个错误是由于备份文件创建时使用的pg_dump版本与尝试恢复时使用的pg_restore版本不匹配所致。更新我的PostgreSQL解决了这个问题。

1
升级到哪个版本了?v12在pg_wrapper中显然有这个问题。你升级到了哪个版本?如果有修复它的12的更新,请告诉我们。 - Bernd Wechner
我已经升级到12.2版本。 - Wariored

1
在我的情况下(在Mac上,Postgres由Homebrew管理),解决方案是检查用于创建转储文件的pg_dump版本,并安装该版本的postgresql。显然,在Brew中,您无法单独安装pg_restore而不安装postgresql(不确定,没有深入研究),因此我需要安装postgresql@12并链接它。就这样。

0
我的pg_restore版本是11.21,我要恢复的文件有这个头部。备份文件的版本是11.18还是15.2?或者有没有可能执行命令来显示pg_dump的备份文件版本? 为了下载相同的Postgres版本,建议使用这个FTP Postgres。

enter image description here

enter image description here


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