我有一个正在运行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)
这有点可疑,但并不明显是因果相关:
- 我正在使用 pg_dump 而不是 psql
- 我只使用 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)
那是令人难以置信的困惑。唯一可能的解释是:
- 尽管报告相同的版本号,但两个pg_dumps是不同的。我会认为这是不可思议的。
- pg_dump运行pg_wrapper,pg_wrapper使用某些神秘参数运行 /usr/lib/postgresql/10/bin/pg_dump 使其崩溃!
- 如果提供了 --host,则使用已安装的最新版本的postgresql(在我的情况下为12,且这是针对pg_dump的,因此pg_dump 12创建了转储文件);
- 如果未提供 --host,则会查阅用户配置(在我的情况下为10,这是针对pg_restore的,因此运行pg_restore 10,但它无法读取由pg_dump 12创建的文件)。
sudo -u postgres pg_restore -l test.backup
这个有效:
sudo -u postgres pg_restore --host=localhost -l test.backup
通过具体指定主机,我们可以让它忽略本地配置,并使用最新版本的pg_restore工具,这似乎能够很好地恢复到PG 10集群。
sudo -u postgres pg_restore --verbose --clean --jobs=4 --disable-triggers --no-acl --no-owner -h localhost -U postgresql -d everest_development dump.psql
,但是它没有起作用。我在导入一个数据库时也遇到了同样的错误。 - LearningRORmuhammad@muhammad-mohsin:~/workspace_ror/everest$ psql -d everest_development -f dump.psql
,那么输入的内容是一个PostgreSQL自定义格式的转储文件。请使用pg_restore命令行客户端将此转储文件恢复到数据库中。 - LearningRORpg_wrapper
应该比它更聪明。解决方法很简单,只需在使用pg_dump
和pg_restore
时明确指定--host
,这会强制它们使用相同版本的postgresql(您系统上安装的最新版本)并保持兼容性。如果您在其中一台计算机上使用了--host
而在另一台计算机上未使用,并且有多个版本的postgresql已安装并且早期版本仍在本地配置中使用,则会出现忘记此问题的情况。 - Bernd Wechner