如何恢复 postgres 备份 - 错误:无法删除当前打开的数据库

pti*_*tim 5 postgresql pg-restore

我正在尝试从不再配置的系统中恢复 postgres 备份,并且根据我的尝试,我收到了一系列错误。

  • 我只有备份,没有可参考的原始服务器
  • 过去我已经成功地从这些生产备份中恢复了,但是自从上次成功后就搞乱了我的本地环境(例如,通过 Homebrew 重新安装了 postgres)
  • 我相信一位前同事(不再可用)已成功恢复此特定备份
  • 我在以下情况下遇到了同样的错误:
    • 尝试使用 postgresql@9.4 进行备份
    • 尝试以前已知良好的数据库版本(使用 postgres 11)

(我已阅读相关/建议的问题,但它们似乎不相关)

使用以下命令(在 bash 脚本中)创建备份:

pg_dump --schema=public -Fc
Run Code Online (Sandbox Code Playgroud)

用于恢复脚本的命令(备份脚本将其作为帮助文本回显)是:

pg_dump --schema=public -Fc
Run Code Online (Sandbox Code Playgroud)

当我在本地运行 restore 命令时,我得到以下信息:

dropdb ${PGDATABASE}
createdb ${PGDATABASE}
time pg_restore \
    -j4 \
    -d ${PGDATABASE} \
    --create \
    --no-privileges \
    --no-owner \
    --clean \
    --if-exists \
    --exit-on-error \
    "${dirname}/${filename}"
Run Code Online (Sandbox Code Playgroud)

以前,我只有在运行几分钟后才会出现“磁盘空间不足错误”,但正如您从time输出中看到的,此错误几乎立即发生!

备份是使用压缩创建的-Fc,我可以使用压缩将备份解压缩为纯文本pg_restore backup.pg_dump > backup.sql,但我无法在其中找到与以下相关的任何命令DROP DATABASE:/

time pg_restore -j4 -d ${PGDATABASE} --create --no-privileges --no-owner --clean --if-exists --exit-on-error ../backups/backup__2019-09-03_16-00-19.pg_dump
pg_restore: [archiver (db)] Error while PROCESSING TOC:
pg_restore: [archiver (db)] Error from TOC entry 4954; 1262 962277 DATABASE mydb mydb
pg_restore: [archiver (db)] could not execute query: ERROR:  cannot drop the currently open database
    Command was: DROP DATABASE IF EXISTS mydb;

real    0m0.049s
user    0m0.019s
sys    0m0.012s
Run Code Online (Sandbox Code Playgroud)

我看到 DB 最初是从那里转储的,9.6.11但我有理由确定我以前用 PG 10 成功恢复了......

我尝试了各种事情,例如:

-- Dumped from database version 9.6.11
-- Dumped by pg_dump version 11.3 (Ubuntu 11.3-1.pgdg14.04+1)
Run Code Online (Sandbox Code Playgroud)

我也尝试从明文转储中恢复失败:

time pg_restore -d ${PGDATABASE} --no-privileges --no-owner --exit-on-error ../backups/backup__2019-09-03_16-00-19.pg_dump
pg_restore: [archiver (db)] Error while PROCESSING TOC:
pg_restore: [archiver (db)] Error from TOC entry 7; 2615 1033373 SCHEMA public mydb
pg_restore: [archiver (db)] could not execute query: ERROR:  schema "public" already exists
    Command was: CREATE SCHEMA public;

ptim:dropdb mydb; createdb mydb
ptim:gizmag ptim$ dropdb mydb

ptim:gizmag ptim$ time pg_restore -d ${PGDATABASE} --create --no-privileges --no-owner --exit-on-error ../backups/backup__2019-09-03_16-00-19.pg_dump
pg_restore: [archiver (db)] connection to database "mydb" failed: FATAL:  database "mydb" does not exist

# guess I misunderstood the create flag!

ptim:gizmag ptim$ dropdb mydb; createdb mydb
dropdb: database removal failed: ERROR:  database "mydb" does not exist

ptim:gizmag ptim$ time pg_restore -d ${PGDATABASE} --create --no-privileges --no-owner --exit-on-error ../backups/backup__2019-09-03_16-00-19.pg_dump
pg_restore: [archiver (db)] Error while PROCESSING TOC:
pg_restore: [archiver (db)] Error from TOC entry 4954; 1262 962277 DATABASE mydb mydb
pg_restore: [archiver (db)] could not execute query: ERROR:  database "mydb" already exists
    Command was: CREATE DATABASE mydb WITH TEMPLATE = template0 ENCODING = 'UTF8' LC_COLLATE = 'en_US.UTF-8' LC_CTYPE = 'en_US.UTF-8';
Run Code Online (Sandbox Code Playgroud)

有什么建议?!

pti*_*tim 15

感谢@a_horse_with_no_name 的提示,我了解到:

-C,--create在恢复之前创建数据库。如果--clean还指定了,则在连接到目标数据库之前删除并重新创建目标数据库。

使用此选项时,名为 with 的数据库-d仅用于发出首字母DROP DATABASECREATE DATABASE命令。所有数据都将恢复到存档中显示的数据库名称中。

(在 dba.stackexchange 进一步解释:为什么 pg_restore 忽略 --create。请注意,在较新版本的pg_restore--create中具有进一步的、不相关的效果)

我的解决方案是删除--create参数:

dropdb ${PGDATABASE}
createdb ${PGDATABASE}
time pg_restore \
    -j4 \
    -d ${PGDATABASE} \
    --no-privileges \
    --no-owner \
    --clean \
    --if-exists \
    --exit-on-error \
    backup.pg_dump
Run Code Online (Sandbox Code Playgroud)

  • 这不是解决方案,您只是停止执行引发错误的操作。请注意您引用的文档说_“如果还指定了 --clean,则在连接**之前删除并重新创建目标数据库”_。这意味着您的 Postgres 版本行为不当,因为这不是它正在做的事情,而是您通过手动删除/创建数据库来解决它。这是 PG < 12 的 --clear 的问题,如您提供的 stackexchange 链接中所述。 (2认同)