Postgresql - 备份数据库并在不同的所有者上恢复?

And*_*ius 62 database postgresql owner database-restore database-backups

我在不同服务器上的数据库上进行备份,并且具有与我需要的不同的角色,使用以下命令:

pg_dump -Fc db_name -f db_name.dump
Run Code Online (Sandbox Code Playgroud)

然后我将备份复制到我需要还原数据库的另一台服务器,但是没有这样的所有者用于该数据库.假设数据库拥有所有者owner1,但在不同的服务器上我只有owner2,我需要恢复该数据库并更改所有者.

我在恢复时在另一台服务器上做了什么:

createdb -p 5433 -T template0 db_name 
pg_restore -p 5433 --role=owner2 -d db_name db_name.dump
Run Code Online (Sandbox Code Playgroud)

但是当运行恢复时,我会收到以下错误:

pg_restore: [archiver (db)] could not execute query: ERROR:  role "owner1" does not exist
Run Code Online (Sandbox Code Playgroud)

如何指定它以便更改所有者?还是不可能?

Gar*_*ary 99

您应该使用该--no-owner选项,这将停止pg_restore尝试将对象的所有权设置为原始所有者.相反,对象将由指定的用户拥有--role

createdb -p 5433 -T template0 db_name 
pg_restore -p 5433 --no-owner --role=owner2 -d db_name db_name.dump
Run Code Online (Sandbox Code Playgroud)

pg_restore doc

  • `pg_dump --no-owner`也应该这样做 (10认同)
  • 我倾向于将这些决定推迟到恢复之前.如果你在转储阶段这样做,这意味着你不能在不进行导出的情况下改变主意.在恢复时执行此操作意味着选项保持打开状态,以防您确定应该创建该缺失角色等. (7认同)
  • 通过查看关于此主题的所有帖子,他们似乎也跳过了这样一个事实:这种方法要求新角色所有者成为超级用户,至少在恢复期间是这样.一切正常 (3认同)
  • @chrismarx 可以使用 `-U <superuser>` 和 `--role <actual_user>` 来代替。 (3认同)
  • @Andrius:你不需要改变备份,Gary的答案应该可以解决你的问题 (2认同)

mat*_*tpr 13

上面的答案很有帮助,但最终并没有让我 100% 满意我的案例,所以我想我会为与我有类似案例的人分享上面的迭代。

在我的场景中,我可能有具有不同名称和不同所有者的临时数据库和生产数据库。我可能需要迁移临时数据库以替换生产数据库,但名称和所有者不同。

或者,也许我需要恢复每日备份,但由于某种原因更改了名称或所有者。

我们的权限相当简单,因为每个应用程序都有自己的数据库/用户,因此这不会帮助具有复杂用户/角色/权限设置的人。

我尝试使用从模板创建方法来复制数据库,但如果任何用户/连接在源数据库上处于活动状态,则会失败,因此这不适用于实时源数据库。

通过基本--no-owner恢复,恢复/新数据库上的数据库/表所有者是执行命令的用户(例如postgres)...因此您将需要一个额外的步骤来修复所有数据库权限。由于我们每个数据库都有一个特定于应用程序的用户设置,因此我们可以使事情变得更容易。

我希望我的应用程序特定用户拥有数据库/表,即使他们一开始没有创建数据库的权限。

基本思想是:

  • --no-owner使用and转储源数据库--no-privileges
    • --clean不需要,因为我们将恢复到新的/空的数据库中。
  • 如果目标数据库已经存在,则删除它。
  • 重新创建目标数据库(空),将所有者设置为我们的目标用户(已经存在,如果不需要创建)。
  • 作为目标用户将转储恢复到空目标
    • --no-owner --no-privileges确保目标用户拥有一切,并且不会从我们制作的转储中继承任何所有权/权限。
    • --no-privileges在这里是--no-owner多余的,因为我们在转储时已经排除了它们。因此,下面的示例中有一些冗余标志,如果您对转储的制作方式有信心,则可能不需要这些标志。

请注意,我放弃了任何特权/所有权,因为每个数据库都有一个用户作为具有完全权限的数据库所有者。如果您有更复杂的权限结构,这可能不合适。或者,您可能使用单用户进行恢复,然后让您的服务器配置系统将任何缺失的角色/权限添加到恢复的数据库中。

例子

设置一些变量...

DB_NAME_SRC="app_staging"
DB_NAME_TARGET="app_production"
DB_TARGET_OWNER="app_production_user"
DUMP_FILE="/tmp/$DB_NAME_SRC"
Run Code Online (Sandbox Code Playgroud)

然后进行备份/恢复

# backup clean/no-owner
sudo -i -u postgres pg_dump --format custom --clean --no-owner --no-privileges "$DB_NAME_SRC" > "$DUMP_FILE"

# THE FOLLOWING HAPPENS ON THE PG box where you want to restore

# drop target if exists - doesn't work for db with active users/connections
sudo -i -u postgres dropdb   -U postgres --if-exists  "$DB_NAME_TARGET"

# recreate target db, specifying owner to be the target user/role
# DB_TARGET_OWNER must already exist in postgres or you need to create it
sudo -i -u postgres createdb -U postgres --owner "$DB_TARGET_OWNER" -T template0 "$DB_NAME_TARGET"

# do the restore to the target db as the target user so any created objects will be owned by our target user.
sudo -i -u postgres pg_restore --host localhost --port 5432 --username "$DB_TARGET_OWNER" --password --dbname "$DB_NAME_TARGET" --no-owner --no-privileges "$DUMP_FILE"

# now in this simple case I don't need an additional step of fixing all the owners/permissions because the db and everything in it will be owned by the target user.
Run Code Online (Sandbox Code Playgroud)

请注意,在恢复部分中,我使用密码通过网络连接,而不是本地连接,因此我不必将 postgres 本地用户身份验证从对等更改为密码。无论如何,我的数据库应用程序特定用户都不是本地用户。