我有一个实时服务器和开发框,分别称它们为live和dev,都在运行postgresql。我可以用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_dmp以某种方式对活动框使用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)
这有点可疑,但同样不是明显的原因或相关因素:
- 我使用的是pg_dump而不是psql
- 我只使用dev-boxes pg工具,而不是live-boxes(它们应该无关紧要,理论上整个数据传输通过live-box上的5432端口,该端口将数据库转储传递到我的dev-boxies上的pg_dump
以下是爱盒上的集群,它位于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)
这令人难以置信地困惑。唯一可能的解释:
- 尽管报告的版本号相同,但两个pg_dump不同。我认为这是难以置信的
- pg_dump运行的是pg_wrapper,它运行/usr/lib/postgresql/10/bin/pg_dmp,其中有一些神秘的参数会破坏它
第二个是合理的,需要我对pg_wrapper进行仪器诊断。
更新2:
以及pg_wrapper的一个仪器。结果表明,pg_dump运行的是运行/usr/lib/postgresql/12/bin/pg_dump
的pg_wrapper,而它运行的是/usr/lib/postgresql/10/bin/pg_restore
。。。想想看吧开始认为这是postgresql版本的互操作性错误!
更新3:
深入研究pg_wrapper
,确定了原因,是的,我认为这是一种pg_wrapper错误,尽管这可能有争议,但很难理解IMHO。它的作用如下:
如果提供了--host
,那么它使用安装的最新版本的postgresql(在我的情况下是12,这是针对pg_dump的,所以pg_dump12创建转储)
如果没有提供--host
,那么它会参考用户配置(在我的情况下是10,这是针对pg_restore的,所以运行pg_restore 10,它不能读取pg_dump 12创建的文件)。
为什么这是一个bug?因为我有一个使用配置,无论我是否与远程主机交谈,我都希望它得到尊重。更重要的是,如果我指定了一个主机,我当然不希望使用最新的本地版本来忽略本地配置。我希望要么尊重本地配置(就像没有指定远程主机的情况一样),要么尝试匹配rmote主机版本。随意依赖最新安装的版本是IMHO非常值得怀疑的。
但事实证明,有一种变通方法是有效的。本质上不是:
sudo -u postgres pg_restore -l test.backup
这项工作:
sudo -u postgres pg_restore --host=localhost -l test.backup
讽刺的是,通过指定主机,我们强迫它忽略本地配置,并使用最新版本的pg_restore,它似乎可以很好地恢复到PG10集群。
ubuntu伙计们:很可能你的pg_restore
已经过时了。只需使用postgres-doc并安装最新版本的postgres:
-
创建文件
/etc/apt/sources.list.d/pgdg.list
并为存储库添加一行:deb http://apt.postgresql.org/pub/repos/apt/ YOUR_UBUNTU_VERSION_HERE-pgdg main
,其中ubuntu版本为:- 20.04-焦点
- 18.04-仿生
- 16.04-xenial
-
添加密钥:
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
-
sudo apt-get update && sudo apt-get upgrade
它对我有用!
所以我在这里的经历有点类似于OP,但并不完全。
我安装了9.4、9.5、11和12版本,所有的pg_*工具都指向9.4版本。我试图在另一台主机上pg_restore版本12创建的转储,但没有成功,因为该主机使用了不兼容的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
选项,它有助于解析版本。所以我只是简单地将--cluster 12/main
添加到我的pg_restore
调用中,一切都如预期一样再次运行
这里还有另一个转折点,但请首先注意,这是一个windows案例。如果它只是为您准备的linux,请不要进一步阅读。这里给出的所有建议都对我没有帮助,最终IMC的原因更简单了,必须使用pgAdmin。由于新版本的nag重复,我的习惯是单独安装pgAdmin(不使用stackbuilder)。(至少)在这种情况下,pgAdmin有自己的实用程序缓存,除非你有不同的说法,否则会使用这些程序。我的pg实例仍然是版本11(.6),但最新的pgAdmin可能会有V12实用程序。这很可能会导致版本差异。在我成功地从主机转移到笔记本电脑后,这件事悄悄地发生了。因此,在pgAdmin do(菜单)File->preferences->Paths中,设置对应于postgres安装的二进制路径,IMC C:\Program Files\PostgreSQL\11\bin。这就完成了任务。
检查您的pgadmin是否是最新的,我遇到了这个问题,并通过更新解决了它
此错误是由用于创建备份文件的pg_dump版本与用于尝试还原的pg_restore版本不匹配引起的。
更新我的PostgreSQL解决了问题
在我的案例中(在Mac上,Postgres由Homebrew管理),解决方案是检查用于创建转储文件的pg_dump版本,并安装该版本的postgresql。
显然,使用Brew,你不能将pg_restore与postgresql分开安装(不确定,没有真正深入研究),所以我需要安装postgresql@12并将其链接起来。就这样。